unit-testing - 从 grails 模拟方法中抛出异常

标签 unit-testing testing grails mocking

在 Grails 的 Controller 单元测试中(更具体地说是 Spock ControllerSpec),我想在协作者抛出异常时检查被测方法的行为。

我正在使用 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()
    }
}

但是测试失败了:

Expected exception java.lang.Exception, but no exception was thrown

我调试了执行并且没有抛出异常,exceptionThrowingMethod 的调用意外地返回了一个闭包。不要介意将 throws 声明添加到方法的签名中,这也不起作用。

我认为这与 Spock 有关,但我只使用 grails 的测试混合尝试了一个类似的测试并得到了相同的结果。这是我的尝试:

@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 的文档中找不到如何要求抛出异常,所以上面的代码对我来说听起来很自然。

我也发现通过谷歌搜索没有找到任何相关的东西是可疑的,所以也许我在测试方面做错了事。

这不是测试中的常见情况吗?您在特定场景中模拟某些方法的确定性行为,然后在这种场景发生时测试被测方法的预期行为。抛出异常对我来说似乎是一个有效的场景。

最佳答案

似乎使 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 被调用一次)。

关于unit-testing - 从 grails 模拟方法中抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9523966/

相关文章:

c# - Moq:在对不返回值的方法进行方法调用后回调

java - 注释以使私有(private)方法仅对测试类公开

c# - 如何使用 Selenium 遍历非选择下拉列表?

angular - 使用 Karma 和 Jasmine/Angular 8 对具有多个并行 API 调用的服务进行单元测试

angular - Angular 测试中访问 MatMenuTrigger 组件实例

javascript - $q 解析函数此时未触发

javascript - 单元测试 ReactJS 组件产生不变违规 : findComponentRoot

grails - 单击“运行”按钮时,grails 2.0在IntelliJ中挂起

grails - 使用下拉列表的出生日期

hibernate - Grails和JPA集成