Async Pact消费者测试报NullPointerException问题排查求助
问题:Async Pact消费者测试抛出空指针异常
我正在为一个使用RabbitMQ的测试应用编写Async Pact消费者测试,应用可正常运行,但创建Pact的测试失败,抛出如下错误:
%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)
Gradle配置文件
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"] }
测试代码
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; } }
背景与尝试
我参考了旧示例代码,升级了Java版本到17、Gradle版本以及Pact版本到4.6.1。应用本身可正常运行,但Pact测试始终抛出空指针异常。我尝试给setMessage方法添加@BeforeEach注解,手动构造消息传入,但问题仍未解决。
现寻求故障排查提示,同时想确认当前Pact版本是否兼容更高版本的Gradle。
故障排查提示
修正消息注入方式:Pact 4.x+的JUnit5异步消息测试已不再通过无注解的
setMessage方法注入消息,而是直接将消息作为测试方法的参数传入。修改测试方法如下:@Test @PactTestFor(pactMethod = "userCreatedMessagePact", providerType = ProviderType.ASYNCH) void verifyCreatePersonPact(byte[] message) throws IOException { messageConsumer.consumeStringMessage(new String(message)); }同时可以移除
currentMessage变量和setMessage方法,避免冗余。检查Pact版本兼容性:当前使用的Pact插件4.6.1与Spring Boot 3.1.0(对应Gradle 7.5+)是兼容的,支持升级到Gradle 7.x或8.x版本。若要升级Gradle,需确保Pact插件版本与Gradle版本匹配:Pact 4.x系列支持Gradle 7.0+,Pact 5.x系列支持Gradle 7.4+及8.x。
验证消息内容构造:确认
PactDslJsonBody构造的消息格式正确,没有遗漏必填字段或格式错误,避免框架因无法生成有效消息而导致注入失败。
内容的提问来源于stack exchange,提问作者Allan Noguera
相关产品推荐
相关产品推荐

