2012-03-01 97 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