Grails 2.0单元测试过滤器:服务注入和依赖



目前正在将grails 1.3.7应用程序升级到2.1.0,并且有一组过滤器我想要测试。正如测试过滤器的grails文档所示,现在支持过滤器的单元测试(/是推荐的?)它在功能部分提到,但没有找到示例),我试图将过滤器的一些现有集成测试转换为单元测试。

然而,我正在努力正确地"模拟"一个过滤器,这个过滤器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代码。我试过将依赖过滤器添加到mock ala:

@Mock([MyFilters, MyOtherFilters]) 

但是,然后我遇到了SomeOtherService方法未定义的问题,并且没有找到正确模拟这些方法的方法(我如何在过滤器上设置服务模拟?在控制器或服务上,你可以def myMock = mockFor(SomeOtherService),然后做controller.someOtherService = myMock.createMock()或类似的东西,但我找不到一种方法来设置这个withFilters块过滤器的服务,文档建议使用。

理想情况下,我会模拟任何与someServiceMyOtherFilters有关的东西,并只是在这个过滤器上编写我的测试,但不确定什么是可能的/测试过滤器。

任何见解将非常感激,非常感谢,如果你做到了这一点!

有同样的问题。Grails Jira中有一个bug http://jira.grails.org/browse/GRAILS-8976

我在http://delvingintodev.carrclan.us/2012/12/testing-grails-filters-that-use-services.html"测试使用服务的Grails过滤器"中找到了解决方法'

你基本上必须在filter中使用service,如下所示

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(){
    }
}

最新更新