Mockserver fails to match expectation for received message

Viewed 1612

I am using

<dependency>
    <groupId>org.mock-server</groupId>
    <artifactId>mockserver-netty</artifactId>
    <version>5.11.2</version>
    <scope>test</scope>
</dependency>

for integration tests of a REST API. I've started with very basic expectations, to further ellaborate the tests later, once the minimum stuff passes the test. To my surpise, MockServer keeps telling me that no received requests match my expectations.

I am using the Java API, to write tests that use Mockito and PowerMock to deal with static methods. TestNG is the Test Freamework.

This is my code:

@PowerMockIgnore({"javax.xml.parsers.*", "org.apache.logging.log4j.*", "com.sun.org.apache.*", "sun.security.*", "javax.net.ssl.*"})
@PrepareForTest({K8sTarget.class, K8sApi.class})

public class DataAccessImplTest extends PowerMockTestCase {

    private static final String HTTP_METHOD_GET = "GET";

    private static final String USER_ID= "46756123123";

    private static final String USERS_PATH = "/api/v1/users/%s";

    private static final String CONTENT_TYPE_APP_JSON = "application/json";

    @Mock
    Target mockTarget;

    @Mock
    K8sClient mockK8sClient;

    private DataAccessFactory dataAccessFactory;

    private DataAccessImpl dataAccessUT;

    private MockServerClient mockServer;

    AutoCloseable closeable;

    @BeforeClass
    public void setup() {

        // ensure all connection using HTTPS will use the SSL context defined by
        // MockServer to allow dynamically generated certificates to be accepted
        HttpsURLConnection.setDefaultSSLSocketFactory(
                new KeyStoreFactory(new MockServerLogger()).sslContext().getSocketFactory());
        this.mockServer = startClientAndServer(PortFactory.findFreePort());

        this.closeable = MockitoAnnotations.openMocks(this);

        dataAccessFactory = DataAccessFactory.getInstance();
        assertNotNull(dataAccessFactory);

        PowerMockito.mockStatic(K8sApi.class);
        PowerMockito.mockStatic(K8sTarget.class);
        PowerMockito.when(K8sApi.getK8sClient()).thenReturn(mockK8sClient);
        PowerMockito.when(K8sTarget.of(Mockito.any(K8sClient.class), Mockito.any(Target.class))).thenReturn(mockTarget);
        Mockito.when(mockTarget.getName()).thenReturn("localhost");
        Mockito.when(mockTarget.getPort()).thenReturn(this.mockServer.getPort().intValue());
        
        dataAccessUT = dataAccessFactory.createDataClient();
    }

    @BeforeMethod
    public void prepareMocks() {

        Mockito.when(mockTarget.getName()).thenReturn("localhost");
        Mockito.when(mockTarget.getPort()).thenReturn(this.mockServer.getPort().intValue());
    }

    @AfterClass
    public void teardown() throws Exception {
        this.closeable.close();
        this.mockServer.stop();
    }

    @Test
    public void getUserTest_200_Ok() throws IOException {

        dataAccessUT.getUserData(USER_ID);

        mockServer.when(request()
                .withMethod(HTTP_METHOD_GET)
                .withPath(String.format(USERS_PATH, USER_ID))
        )
        .respond(
            response()
                .withStatusCode(HttpStatusCode.OK_200.code())
                .withHeader(HttpHeaderNames.CONTENT_TYPE.toString(), CONTENT_TYPE_APP_JSON)
                .withBody("some_response_body")
        );
    }
}

and these are the console logs:

10:06:24.067 [nioEventLoopGroup-2-1] DEBUG com.commonlibrary.httpclient.common.HttpConnectionListener:28 - 0.1 HttpConnectionListener::operationComplete: connected to [localhost:58136] from [/127.0.0.1:58204]
10:06:24.285 [MockServer-EventLog0] INFO  org.mockserver.log.MockServerEventLog:108 - 58136 received request:

  {
    "method" : "GET",
    "path" : "/api/v1/users/46756123123",
    "headers" : {
      "authorization" : [ "Bearer token" ],
      "accept" : [ "application/json" ],
      "host" : [ "localhost:58136" ],
      "content-length" : [ "0" ]
    },
    "keepAlive" : true,
    "secure" : false
  }

10:06:24.350 [MockServer-EventLog0] INFO  org.mockserver.log.MockServerEventLog:108 - 58136 no expectation for:

  {
    "method" : "GET",
    "path" : "/api/v1/users/46756123123",
    "headers" : {
      "authorization" : [ "Bearer token" ],
      "accept" : [ "application/json" ],
      "host" : [ "localhost:58136" ],
      "content-length" : [ "0" ]
    },
    "keepAlive" : true,
    "secure" : false
  }

 returning response:

  {
    "statusCode" : 404,
    "reasonPhrase" : "Not Found"
  }

10:06:24.483 [MockServer-EventLog0] INFO  org.mockserver.log.MockServerEventLog:108 - 58136 stopped for port: 58136

As you can see (unless I am missing something) request should match the expectation, but it doesn'. I have tried several things, all of them without success:

  • reduce the request expectation to the bare minimum, just calling request() without defining anything else. This shouls match EVERY incoming request. Same result.
  • introduce Times.exactly(1) in the expectation. Same result.
  • specify the headers I am sending in the request, even though my understanding is that if they are not set in the expectation, they are not used for matching. Same result.

After 2 days, I am running out of ideas, so any help or hint would be appreciated. Thanks!

Edition after following hint and checking code examples in MockServer site

Following @peter-rowth suggestion, I moved the request sent after creating expectations and it worked. I am editing this issue also to make clear that it duplicates [https://stackoverflow.com/questions/63843619/mockserver-request-not-found][1], that I found later.
1 Answers

It looks like in your test you are creating the expectations in MockServer after executing the call to your code under test? The fact that your console output from MockServer does not output matched/not matched expectations (the default behavior) indicated to me that there are no expectations setup when the web request is made to MockServer and a 404 is default response by MockServer when there is no expectation for a request.

Try adding that expectation as the first line in your test.

Related