2012-03-01 129 views
4

在Grails的控制器單元測試(更具體地說是Spock ControllerSpec)上,我想檢查協作者拋出異常時測試方法的行爲。從grails模擬方法拋出異常

我使用mockFor實用程序(無論是從Spock的UnitSpec或Grails的GrailsUnitTestMixin)來指定在測試我對這種異常拋出方法的要求,如:

@TestFor(TestController) 
class TestControllerSpec extends Specification { 

    def "throwing and exception from a mock method should make the test fail"() { 
     setup: 
     def serviceMock = mockFor(TestService) 
     serviceMock.demand.exceptionThrowingMethod() { throw new Exception() } 
     controller.testService = serviceMock.createMock() 

     when: 
     controller.triggerException() 

     then: 
     thrown(Exception) 
    } 
} 

所以,裏面triggerException我調用exceptionThrowingMethod,像這樣:

class TestController { 

    def testService 

    def triggerException() { 
     testService.exceptionThrowingMethod() 
    } 
} 

但測試失敗,如:

預期異常java.lang.Exception的,但沒有引發異常

我調試的excecution和異常沒有拋出beign的exceptionThrowingMethod的invokation出奇返回閉幕。 Nevermind將throws聲明添加到方法的簽名中也不起作用。

我認爲這與Spock有關,但我嘗試了使用grails的測試mixin進行simliar測試,得到了相同的結果。這是我的嘗試:

@TestFor(TestController) 
class TestControllerTests { 

    void testException() { 
     def serviceMock = mockFor(TestService) 
     serviceMock.demand.exceptionThrowingMethod() { throw new Exception() } 
     controller.testService = serviceMock.createMock() 

     shouldFail(Exception) { 
      controller.triggerException() 
     } 
    } 
} 

您是否在我的代碼中發現任何錯誤?

在Grails的文檔中,我無法找到如何要求拋出異常,所以上面的代碼聽起來很自然。

我也發現它可疑沒有發現任何與Google搜索有關的任何內容,所以也許我試圖做錯關於測試的事情。

這不是測試中的常見情況嗎?您可以在特定場景中嘲笑某種方法的確定性行爲,然後在發生此類情況時測試待測試方法的預期行爲。拋出異常對我來說看起來像是一個有效的場景。

回答

8

似乎使得demand關閉譯註(即無隱it說法,有一個明確的->does the trick

serviceMock.demand.exceptionThrowingMethod {-> throw new Exception() } 

更新:您還可以使用Groovy的原生MockFor類,這似乎並不需要這種封閉怪異性:

@TestFor(TestController) 
class TestControllerTests { 

    void testException() { 
     def mock = new MockFor(TestService) 
     mock.demand.exceptionThrowingMethod { throw new Exception() } 
     controller.testService = mock.proxyInstance() 

     shouldFail { controller.triggerException() } 
     mock.verify(controller.testService) 
    } 
} 

請注意,當不使用mock.use時,必須使用mock.verify以驗證模擬約束(即,那exceptionThrowingMethod被調用過一次)。

+0

順便說一句,我也想知道這是否是測試中的常見情況:D – epidemian 2012-03-01 22:01:16

+1

TIL about niladic – doelleri 2012-03-01 22:23:34

+0

@doelleri Maybe [「nullary」](http://en.wikipedia.org/wiki/Arity# Nullary)是一個更常見的同義詞,但我認爲「niladic」聽起來好多了! – epidemian 2012-03-01 22:49:46