javagradlepactpact-brokerasynctest

Pact Async Consumer Test is failing with message null


I am testing to create a Async Pact for a test application, that uses RabbitMQ I got the application running but the test to create the pact fails with the following error.

%TESTS  3,verifyCreatePersonPact(io.reflectoring.MessageConsumerTest)

%ERROR  3,verifyCreatePersonPact(io.reflectoring.MessageConsumerTest)
%TRACES 
java.lang.NullPointerException: Cannot read the array length because "bytes" is null
        at java.base/java.lang.String.<init>(String.java:1437)
        at io.reflectoring.MessageConsumerTest.verifyCreatePersonPact(MessageConsumerTest.java:45)

Here is the gradle file:

plugins {
    id 'org.springframework.boot' version '3.1.0'
    id 'io.spring.dependency-management' version '1.1.0'
    id 'java'
    id 'au.com.dius.pact' version '4.6.1'
    id 'java-library'
}

version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {

    implementation 'org.springframework.boot:spring-boot-starter-web' 
    implementation 'org.springframework.boot:spring-boot-starter-amqp'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
 
    implementation 'com.h2database:h2:1.4.196'
    compileOnly 'org.projectlombok:lombok:1.18.2' 
    runtimeOnly 'javax.xml.bind:jaxb-api:2.3.1'
    runtimeOnly 'org.javassist:javassist:3.23.1-GA'

    testImplementation 'org.springframework.boot:spring-boot-starter-test' 
    testImplementation 'au.com.dius.pact.consumer:junit5:4.6.1'
}

test {
    useJUnitPlatform()
}

bootRun {
    jvmArgs = ["-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"]
}

And here is the Test file

package io.reflectoring;

import java.io.IOException;

import au.com.dius.pact.consumer.MessagePactBuilder;
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt;
import au.com.dius.pact.consumer.junit5.PactTestFor;
import au.com.dius.pact.consumer.junit5.ProviderType;
import au.com.dius.pact.core.model.annotations.Pact;
import au.com.dius.pact.core.model.messaging.MessagePact;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;

@ExtendWith(PactConsumerTestExt.class)
public class MessageConsumerTest {

    private byte[] currentMessage;

    @Autowired
    private MessageConsumer messageConsumer;

    @Pact(provider = "userservice", consumer = "userclient")
    public MessagePact userCreatedMessagePact(MessagePactBuilder builder){
        PactDslJsonBody body = new PactDslJsonBody();
        body.stringType("messageUuid");
        body.object("user")
            .numberType("id", 42L)
            .stringType("name", "Zaphod Beeblebrox")
                        .closeObject();

        // @formatter:off
        return builder
            .expectsToReceive("a user created message")
            .withContent(body)
            .toPact();
        // @formatter:on
    }

        @Test 
    @PactTestFor(pactMethod = "userCreatedMessagePact", providerType = ProviderType.ASYNCH)
    void verifyCreatePersonPact() throws IOException {
        messageConsumer.consumeStringMessage(new String(this.currentMessage));
    }

    /**
     * This method is called by the Pact framework.
     */
    public void setMessage(byte[] message) {
        this.currentMessage = message;
    }
}

I am following this example: https://github.com/thombergs/code-examples/blob/master/pact/pact-message-consumer/src/test/java/io/reflectoring/MessageConsumerTest.java

But I am updating the java version, gradle and also the pact version.

Thanks for your help.

So I already tried adding @BeforeEach to the setMessage method. And crafting the message there too.

If someone could give me a hint on what could be failing? Also if it works with a later version of gradle it would be great.


Solution

  • I don't think setMessage is a thing, or at least it's not anymore.

    An example project using a relatively recent version can be found here: https://github.com/pactflow/example-consumer-java-kafka/blob/master/src/test/java/io/pactflow/example/kafka/ProductsPactTest.java#L49

      @Test
      @PactTestFor(pactMethod = "createPact")
      void test(List<Message> messages) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        System.out.println("Message received -> " + messages.get(0).contentsAsString());
        Product product = mapper.readValue(messages.get(0).contentsAsString(), Product.class);
    
        assertDoesNotThrow(() -> {
          listener.listen(product);
        });
      }
    

    Note how the message is injected directly into the test.