ont*_*ntk 9 grails groovy unit-testing spock
我正在尝试对具有需要请求对象的方法的服务进行单元测试.
import org.springframework.web.context.request.RequestContextHolder as RCH
class AddressService {
def update (account, params) {
try {
def request = RCH.requestAttributes.request
// retrieve some info from the request object such as the IP ...
// Implement update logic
} catch (all) {
/* do something with the exception */
}
}
}
Run Code Online (Sandbox Code Playgroud)
你如何模拟请求对象?
顺便说一句,我正在使用Spock对我的课进行单元测试.
谢谢
模拟这些的一种简单方法是修改元类,RequestContextHolder以便在getRequestAttributes()调用时返回模拟.
我为此做了一个简单的规范,当它不起作用时非常惊讶!所以这被证明是一个非常有趣的问题.经过一番调查,我发现在这种特殊情况下,有一些陷阱需要注意.
当您检索请求对象时RCH.requestAttributes.request,您是通过RequestAttributes未实现该getRequest()方法的接口执行此操作.如果返回的对象实际上具有此属性,则在groovy中完全正常,但RequestAttributes在spock中模拟接口时将无法工作.因此,您需要模拟实际具有此方法的接口或类.
我第一次尝试解决1.,是将模拟类型更改为ServletRequestAttributes,确实有一个getRequest()方法.但是,这种方法是最终的.当使用最终方法的值来存储模拟时,简单地忽略存根值.在这种情况下,null被退回.
通过为此测试创建一个自定义接口(称为)MockRequestAttributes,可以轻松克服这两个问题,并在规范中使用此接口作为Mock.
这导致以下代码:
import org.springframework.web.context.request.RequestContextHolder
// modified for testing
class AddressService {
def localAddress
def contentType
def update() {
def request = RequestContextHolder.requestAttributes.request
localAddress = request.localAddr
contentType = request.contentType
}
}
Run Code Online (Sandbox Code Playgroud)
import org.springframework.web.context.request.RequestAttributes
import javax.servlet.http.HttpServletRequest
interface MockRequestAttributes extends RequestAttributes {
HttpServletRequest getRequest()
}
Run Code Online (Sandbox Code Playgroud)
import org.springframework.web.context.request.RequestContextHolder
import spock.lang.Specification
import javax.servlet.http.HttpServletRequest
class MockRequestSpec extends Specification {
def "let's mock a request"() {
setup:
def requestAttributesMock = Mock(MockRequestAttributes)
def requestMock = Mock(HttpServletRequest)
RequestContextHolder.metaClass.'static'.getRequestAttributes = {->
requestAttributesMock
}
when:
def service = new AddressService()
def result = service.update()
then:
1 * requestAttributesMock.getRequest() >> requestMock
1 * requestMock.localAddr >> '127.0.0.1'
1 * requestMock.contentType >> 'text/plain'
service.localAddress == '127.0.0.1'
service.contentType == 'text/plain'
cleanup:
RequestContextHolder.metaClass = null
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码似乎适用于基本单元测试(修改自Robert Fletcher的帖子):
void createRequestContextHolder() {
MockHttpServletRequest request = new MockHttpServletRequest()
request.characterEncoding = 'UTF-8'
GrailsWebRequest webRequest = new GrailsWebRequest(request, new MockHttpServletResponse(), ServletContextHolder.servletContext)
request.setAttribute(GrailsApplicationAttributes.WEB_REQUEST, webRequest)
RequestContextHolder.setRequestAttributes(webRequest)
}
Run Code Online (Sandbox Code Playgroud)
它可以作为函数添加到标准Grails单元测试中,因为函数名称不以"test"开头......或者您可以通过其他方式处理代码.
| 归档时间: |
|
| 查看次数: |
6660 次 |
| 最近记录: |