spring-bootjunit5pactpact-jvm

Pact consumer contact gives au.com.dius.pact.consumer.PactMismatchesException


I am new to Pact contract testing

Gradle dependencies

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    
    //pact
    testImplementation 'au.com.dius.pact.consumer:junit5:4.3.6'
}

Rest Controller

@RestController
public class CodeController {
    
    @GetMapping("/hello")
    public String hello() {
        return "Hello from spring with pact project";
    }
}

ControllerClient

@Component
public class ControllerClient{
    private final RestTemplate restTemplate;

    public ControllerClient(@Value("${user-service.base-url}") String baseUrl) {
        this.restTemplate = new RestTemplateBuilder().rootUri(baseUrl).build();
    }
    
    public String getHello() {
        return restTemplate.getForObject("/hello", String.class);
    }
}

ConsumerContractTest

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = "user-service.base-url:http://localhost:8080", classes = ControllerClient.class)
@ExtendWith(PactConsumerTestExt.class)
public class ConsumerContractTest {

    @Autowired
    private ControllerClient controllerClient;

    @Pact(consumer = "code-consumer")
    public RequestResponsePact pactForHelloWorld(PactDslWithProvider builder) {
        return builder
                .given("hello world")
                .uponReceiving("hello request")
                    .path("/hello")
                    .method(HttpMethod.GET.name())
                .willRespondWith().status(200)
                    .body(new PactDslJsonBody().stringType("Hello from spring with pact project"))
                .toPact();
    }

    @PactTestFor(pactMethod = "pactForHelloWorld", pactVersion = PactSpecVersion.V3)
    @Test
    public void userExists() {
        String returnStr = controllerClient.getHello();
        assertThat(returnStr).isEqualTo("Hello from spring with pact project");
    }
}

When I execute this consumer contract test I get below exception

au.com.dius.pact.consumer.PactMismatchesException: The following requests were not received:
    method: GET
    path: /hello
    query: {}
    headers: {}
    matchers: MatchingRules(rules={})
    generators: Generators(categories={})
    body: MISSING
    at au.com.dius.pact.consumer.junit.JUnitTestSupport.validateMockServerResult(JUnitTestSupport.kt:110)
    at au.com.dius.pact.consumer.junit5.PactConsumerTestExt.afterTestExecution(PactConsumerTestExt.kt:468)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterTestExecutionCallbacks$9(TestMethodTestDescriptor.java:233)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$13(TestMethodTestDescriptor.java:273)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$14(TestMethodTestDescriptor.java:273)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    ....

Solution

  • The issue is that your test doesn't send the request to the Pact mock service - that's why you're getting the error "The following requests were not received".

    You should modify your unit test as follows:

        @PactTestFor(pactMethod = "pactForHelloWorld", pactVersion = PactSpecVersion.V3)
        @Test
        public void userExists(MockServer mockServer) {
            // TODO: set endpoint on controllerClient to mockServer.getUrl()
            String returnStr = controllerClient.getHello();
            assertThat(returnStr).isEqualTo("Hello from spring with pact project");
        }
    

    See an example of this approach here.