目前正在将grails 1.3.7 app升级到2.1.0并拥有一组我想测试的过滤器。看到grails documentation for testing filters表明现在支持过滤器的单元测试(/推荐?它在功能部分中提到但未找到示例),我试图将过滤器的一些现有集成测试转换为单元测试
然而,我正在努力正确地“嘲笑”过滤器此过滤器dependsOn
/至少正确地为正在注入过滤器的service
实现模拟。
package com.example
import ... // excluded for brevity
class MyFilters {
GrailsApplication grailsApplication
SomeService someService
def dependsOn = [MyOtherFilters]
def filters = {
all(controller: 'controllerToExclude', invert: true) {
before = {
if (grailsApplication.config.someConfigProperty) {
def someProperty = request.getAttribute('MY_ATTRIBUTE')
if (someProperty = someService.someMethod()) {
redirect(url: someService.getNewUrl(session))
return false
}
}
return true
}
}
}
}
另一个过滤器:
package com.example
class MyOtherFilters {
SomeOtherService someOtherService
def filters = {
all(controller: '*', action: '*') {
before = {
def foo
if (params[MY_ATTRIBUTE]) {
foo = params[MY_ATTRIBUTE]
someOtherService.setMyAttribute(sitePreference, request)
}
if (!foo) {
foo = someOtherService.getMyAttribute(request)
}
if (foo) {
request.setAttribute('MY_ATTRIBUTE', foo)
}
return true
}
}
}
}
这是我正在使用的两个过滤器的真正骨架简化版本(如果有人好奇,他们会读取移动与桌面的偏好,然后根据该偏好进行过滤)。
所以我写的测试看起来大致如下:
package com.example
import grails.test.mixin.TestFor // ... etc more imports here
@TestFor(SomeController)
@Mock(MyFilters) // TODO what goes here???
class MyFiltersTests {
static final IPAD_USER_AGENT = 'Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X; en-us) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B176 Safari/7534.48.3'
static final NON_MOBILE_USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.12011-10-16 20:23:00'
void testFilterRedirects() {
grailsApplication.config.someConfigProperty = true
// actual filter logic acts on this user-agent through some service calls, would like to mock it out though
request.addHeader("user-agent", IPAD_USER_AGENT)
def result
withFilters(action: "index") {
result = controller.index()
}
//assertSomething on result perhaps
assertEquals "myExpectedRedirectUrl", response.redirectedUrl
}
}
正如此代码所示,它甚至不执行MyFilters
代码。我已经尝试将依赖过滤器添加到模拟ala:
@Mock([MyFilters, MyOtherFilters])
但是我遇到了SomeOtherService
方法未定义的问题,并且没有找到正确模拟这些方法的方法(如何在控制器或服务上设置过滤器上的服务模拟?可以def myMock = mockFor(SomeOtherService)
,然后执行controller.someOtherService = myMock.createMock()
或类似的东西,但我找不到使用文档建议使用的withFilters
块为过滤器设置服务的方法。
理想情况下,我会嘲笑与someService
和MyOtherFilters
有关的任何事情,只是在此过滤器上编写我的测试,但不确定测试过滤器的可能性。
如果你做到这一点,非常感谢任何见解!
答案 0 :(得分:2)
有同样的问题。 Grails Jira http://jira.grails.org/browse/GRAILS-8976
中出现了一个错误我在http://delvingintodev.carrclan.us/2012/12/testing-grails-filters-that-use-services.html'测试使用服务的Grails过滤器中找到了解决方法 '
您基本上必须使用过滤器中的服务,如下所示
package xxx.me
class MyFilters {
def filters = {
all(controller:'*', action:'*') {
before = {
applicationContext.getBean(MyService).doSomethingClever()
}
}
}
}
在这种情况下,您将能够在单元测试中模拟它
package xxx.me
@TestMixin(GrailsUnitTestMixin)
@Mock(MyFilters)
class MyFiltersTests {
@Test
public void testFilter(){
defineBeans {
myService(StubbedMyService)
}
SimpleController controller = mockController(SimpleController);
withFilters(controller:"simple" , action:"index"){
controller.index()
}
}
}
class StubbedMyService extends MyService {
def doSomethingClever(){
}
}