2013-02-10 54 views
1

我試圖在動態腳手架控制器的集成測試中模擬服務。我收到一個錯誤,指出服務的控制器屬性不能從測試中訪問。如何在動態腳手架Grails控制器的集成測試中模擬服務?

似乎動態腳手架的控制器不能用單元測試進行測試,所以我正在使用集成測試。我想嘲笑服務來測試我的應用程序中的錯誤處理。這是Grails 2.2.0中的錯誤還是我做錯了?

grails test-app的結果是:

groovy.lang.MissingPropertyException: No such property: myService for class: MyController 

實施例:

我已修改src/templates/scaffolding/Controller.groovy

class ${className}Controller { 
    MyService myService 

    def action() { 
    render myService.serviceMethod() 
    } 
} 

動態腳手架MyController.groovy

class MyController { 
    static scaffold = MyDomainClass 
} 

集成測試MyControllerTests.groovy

class MyControllerTests extends GroovyTestCase { 
    def myController 

    @Before 
    void setUp() { 
    myController = new MyController() 
    } 

    void testMock() { 
    myController.myService = [ serviceMethod : { return "foo" } ] as MyService 
    controller.action() 
    } 
} 

回答

2

嘗試使用setter方法:

void testMock() { 
    myController.setMyService([ serviceMethod : { return "foo" } ]) 
    controller.action() 
} 

如果執行:println c.metaClass.methods*.name,你會看到有像getSetMyService()和getGetMyService()方法。我不確定它,但可能Grails不添加字段,而是get字段get/set方法的getters。

+0

謝謝! controller.setXxxService()方法取得了訣竅!不過,作爲參數的Map需要一個類型轉換:'controller.setMyService([...]作爲MyService)'。此外,您需要將服務重置爲真正的服務以進行下一個測試。 Grails在設置好之後似乎會保持模擬。我將在下面的另一個答案中顯示一個示例實現。 – apa64 2013-02-10 17:03:05

0

集成測試應執行如下所示。如果我們在測試中嘲笑服務,我們必須自行重置。對於我們來說Grails並不是那麼神祕,因爲控制器是在setUp()中創建的。

droggo上面的答案揭示了在SUT中注入模擬的正確方法。我還會添加一個使用Groovy模擬的例子。但有點冗長。

class MyControllerTests extends GroovyTestCase { 
    def myController 
    def myService 

    @Before 
    void setUp() { 
    myController = new MyController() 
    } 

    @After 
    void tearDown() { 
    myController.setMyService(myService) 
    } 

    void testMapMock() { 
    myController.setMyService([ serviceMethod : { return "foo" } ] as MyService) 
    controller.action() 
    } 

    void testGroovyMock() { 
    def myServiceMockContext = new StubFor(MyService) 
    myServiceMockContext.demand.serviceMethod() { -> return "bar" } 
    def myService = myServiceMockContext.proxyInstance() 
    controller.setMyService(myService) 
    controller.action() 
    } 
} 
相關問題