首页 > 解决方案 > 如何让 Spock 在类似于 Mockito 的 Reactor 中匹配?

问题描述

我正在尝试测试一个类,如果null提供了一个值,它将调用另一个 Web 服务来获取数据。我的 JUnit + Mockito 测试效果很好,但我无法让我的 Spock 测试在then:块中匹配。Spock 测试期间返回的错误是:

Suppressed: java.lang.NullPointerException: Cannot invoke method map() on null object

这是因为我的模拟方法不匹配,因此返回null.

Spock测试(不工作)


class MySpec extends Specfication {

    def mockCollaboratingService = Mock(CollaboratingService)
    def service = new MyService(collaboratingService: mockCollaboratingService)

    def "should call another service if the provided start value equals null"() {
        given:
        def id = 123
        def startDate = null

        when: "the service is called"
        def result = service.getTransactions(id, startDate)

        then:
        1 * mockCollaboratingService.getData(id) >> Mono.just(new SomeMockResponse(key: "123"))

        StepVerifier
            .create(result)
            .consumeNextWith({
                // assertions here
            })
            .verifyComplete()
    }
}

JUnit + Mockito(工作)


class AnotherSpec {
    def mockCollaboratingService = Mockito.mock(MockCollaboratingService)
    def service = new MyService(collaboratingService: mockCollaboratingService)

    @Test
    @DisplayName("should call the statement service if the given start date is null")
    void shouldCallStatementServiceIfStartDateEqualsNull() {
        def id = 123
        def startDate = null

        // and some fake data returned from the api
        Mockito.when(mockCollaboratingService.getData(id)).thenReturn(Mono.just(new SomeMockResponse(key: "123")))

        //when
        def result = service.getTransactions(id, null)

        //then
        StepVerifier
                .create(result)
                .consumeNextWith({
                    Mockito.verify(mockStatementService, Mockito.times(1)).getLastStatement(enterpriseToken)
                    assert it.transactionId == 123
                })
                .verifyComplete()
    }
}

标签: groovyjunitmockitoproject-reactorspock

解决方案


Spock 处理 mocking 与 mockito 不同,看看结合 mocking 和 stubbing。此外,所有交互都必须在then块之前完成,因为 Spock 会首先验证它们。使用反应器,实际上StepVerifier是在执行代码。这条线def result = service.getTransactions(id, startDate)只会创建一个冷的 Mono/Flux,但不会产生任何效果。

因此,您必须稍微重新排序测试。

class MySpec extends Specfication {

    def mockCollaboratingService = Mock(CollaboratingService)
    def service = new MyService(collaboratingService: mockCollaboratingService)

    def "should call another service if the provided start value equals null"() {
        given:
        def id = 123
        def startDate = null

        when: "the service is called"
        def result = service.getTransactions(id, startDate)

        and: "code is executed"
        StepVerifier
            .create(result)
            .consumeNextWith({
                // no explicit mock assertions necessary
                assert it.transactionId == 123
            })
            .verifyComplete()

        then:
        1 * mockCollaboratingService.getData(id) >> Mono.just(new SomeMockResponse(key: "123"))

    }
}

推荐阅读