I am trying to implement pact testing for my APIs. I am able to define the contract on the consuming side and upload it to the Pact broker. On my provider API, I have fetched the contract from the broker but when trying to verify the contract, my test is failing because the service layer is being executed instead of being stubbed - which in turn results to ResourceNotFoundException: Client client1 with app myapp not found
- A custom exception thrown if no client
found in database.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ExtendWith(SpringExtension.class)
@Provider("lockedOut_identityService")
@PactBroker(url = "http://localhost:9292")
@ExtendWith(MockitoExtension.class)
public class AuthServiceProviderTest {
@Mock
private ClientService clientService;
@Value("${local.server.port}")
private int port;
@BeforeEach
void before(PactVerificationContext context) {
context.setTarget(new HttpTestTarget("localhost", port, "/"));
}
@TestTemplate
@ExtendWith(PactVerificationInvocationContextProvider.class)
void pactVerificationTestTemplate(PactVerificationContext context) {
if (context != null) {
context.verifyInteraction();
}
}
@State("Get client by appName & clientId")
public void getClient() {
when(clientService.getClient(eq(null), any(String.class), any(String.class)))
.thenReturn(ClientResponse.builder()
.id(1L)
.clientId("client1")
.clientSecret("secret")
.authMethod(null)
.authGrantType(null)
.redirectUri("redirectUri")
.createdAt(LocalDateTime.now())
.build());
}
}
It seems as though the when(clientService.getClient(eq(null), any(String.class), any(String.class)))
is not actually stubbing the service layer.
Controller:
@GetMapping("/get-client")
public ResponseEntity<ClientResponse> getClient(
@RequestHeader(value = "x-correlation-id", required = true) String correlationId,
@RequestParam(value = "id", required = false) Long id,
@RequestParam(value = "appName", required = false) String appName,
@RequestParam(value = "clientId", required = false) String clientId
) {
if ((id == null && appName != null && clientId == null)
|| (id == null && appName == null)) {
throw new InvalidRequestException(ErrorConstant.INVALID_REQUEST.getValue());
}
return new ResponseEntity<>(clientService.getClient(id, appName, clientId), HttpStatus.OK);
}
Controller endpoint being invoked with values: id: null, appname: "myapp", clientId: "client1"
What have I missed? Seems like from Mockito end, things look fine. Have I missed any additional Pact config to use the Mockito stubbing?
Using dependencies:
implementation 'au.com.dius.pact.provider:junit5:4.6.3'
If you are using @SpringBootTest
you need to annotate mocked objects with @MockBean
to get them injected into Spring context. This means that beans created by Spring will use your @MockBean as their dependencies.