【问题标题】:How to get Spock to match in Reactor similar to Mockito?如何让 Spock 在类似于 Mockito 的 Reactor 中匹配?
【发布时间】:2021-03-10 13:21:22
【问题描述】:

如果提供了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()
    }
}

【问题讨论】:

    标签: groovy junit mockito project-reactor spock


    【解决方案1】:

    Spock 处理模拟的方式与 mockito 不同,请查看 combining mocking and stubbing。此外,所有交互都必须在 then 块之前完成,因为 Spock 会首先验证它们。使用 reactor,实际上是 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"))
    
        }
    }
    

    【讨论】:

    • 成功了——你知道如果我在返回的Mono 上调用map,我怎样才能让Spock 匹配map 内的调用?我收到了Too few invocations for 1 * mockMapper.mapTransaction(_) >> Mono.just(new Transaction())
    • 我认为这与感冒有关Mono...但我不确定
    • 不看代码很难说,但基本原理还是一样的,你需要在then块中列出所有交互,在when块中执行你的代码。
    • 被测系统如下所示:service.getData(id).map({ anotherService.mapTransaction(it) }) 而我的 then 块如下所示:1 * mockService.getData(id) >> Mono.just(new SomeMockResponse()) 1 * mockAnotherService.mapTransaction(_) >> Mono.just(new Transaction())
    猜你喜欢
    • 2012-06-06
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    • 2021-06-29
    • 2018-07-01
    相关资源
    最近更新 更多