7

現在、grails 1.3.7 アプリを 2.1.0 にアップグレードしており、テストしたいフィルターのセットがあります。フィルターをテストするためのgrails ドキュメントが、フィルターの単体テストがサポートされるようになったことを示唆しているように (/推奨されますか? 機能部分で言及されていますが、例が見つかりません)、フィルターの既存の統合テストを単体テストに変換しようとしています。 .

ただし、このフィルターを適切に「モック化」するのに苦労していますdependsOn/少なくともservice、フィルターが注入されているいくつかの s のモックを適切に実装します。

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
            }
        }
    }
}

これは、私が使用している 2 つのフィルターの非常に骨組みを簡略化したバージョンです (興味がある方は、モバイルとデスクトップの設定を読み取り、その設定に基づいてフィルター処理を行ってください)。

したがって、私が書いているテストはおおよそ次のようになります。

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、ドキュメントが使用を提案しているこのブロックでフィルターのサービスを設定する方法が見つかりません。

理想的には、someServiceandに関係するものはすべてモックアウトしMyOtherFilters、このフィルターでテストを書くだけですが、フィルターのテストで何が可能かはわかりません。

ここまでお進みいただきありがとうございます。

4

1 に答える 1

2

同じ問題があります。Grails Jira で発生したバグがありますhttp://jira.grails.org/browse/GRAILS-8976

http://delvingintodev.carrclan.us/2012/12/testing-grails-filters-that-use-services.html 'Testing Grails Filters that use Services'で回避策を見つけました

基本的に、次のようにフィルターでサービスを使用する必要があります

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(){
    }
}
于 2013-03-26T14:30:59.277 に答える