Search code examples
groovyspring-webfluxproject-reactorspockreactive

StepVerifier::expectError accepts any exception in Spock


I'm testing a class that uses Spring Boot's webflux library, and I've encountered strange behavior with StepVerifier::expectError. Specifically, I can pass any type (even String!) to the method and the test passes. My method under test should respond with an error Mono for this particular test, and the mono should contain a custom exception. My understanding from this SO question is that I have the StepVerifier operating in the correct block. What is going wrong here?

Class under test:

@Service
@RequiredArgsConstructor
public class PaymentsBO {
    private final ContractClient contractClient;

    public Mono<Void> updatePaymentInfo(Request record) {
        return contractClient
                .getContract(UUID.fromString(record.getContractUuid()))
                .onErrorResume(throwable -> Mono.error(() -> new CustomException(
                        "Contract Service responded with a non-200 due to "
                                + throwable.getCause())))
                .flatMap(
                    // happy-path logic
                );
    }
}

Unit test:

def "Returns an error if the Contract Service returns a non-200"() {
    given:
    def testSubject = new PaymentsBO(contractServiceMock)
    def contractServiceMock = Mock(ContractClient)
    
    when:
    def result = testSubject.updatePaymentInfo(record)

    and:
    StepVerifier.create(result)
        .expectError(String.class)

    then:
    1 * contractServiceMock.getContract(CONTRACT_UUID) >> Mono.error(new ContractServiceException())
}

Solution

  • In StepVerifier docs we can read that verification must be triggered by calling one ot the verify methods

    Trigger the verification of the resulting StepVerifier on its Publisher using either verify() or verify(Duration). (note some of the terminal expectations above have a "verify" prefixed alternative that both declare the expectation and trigger the verification). https://projectreactor.io/docs/test/release/api/reactor/test/StepVerifier.html

    Your code doesn't use a verify method.

    Please consider these two cases:

        @Test
        void without_verify() {
            Mono.error(new IllegalArgumentException(""))
                    .as(StepVerifier::create)
                    .expectError(NullPointerException.class);
        }
        @Test
        void with_verify() {
            Mono.error(new IllegalArgumentException(""))
                    .as(StepVerifier::create)
                    .expectError(NullPointerException.class)
                    .verify();
        }
    

    without_verify is passing because no verification has been triggered.

    with_verify is failing because verification has been triggered.