Prevent expectations already declared exception when testing AsyncRestTemplate

Viewed 738

How can one test AsyncRestTemplate requests and avoid the java.lang.IllegalStateException: Expectations already declared exception? The exception is thrown inconsistently for a single test case.

Java.lang.IllegalStateException: Expectations already declared at org.springframework.util.Assert.state(Assert.java:70) at org.springframework.test.web.client.SimpleRequestExpectationManager.afterExpectationsDeclared(SimpleRequestExpectationManager.java:47) at org.springframework.test.web.client.AbstractRequestExpectationManager.validateRequest(AbstractRequestExpectationManager.java:73) at org.springframework.test.web.client.MockRestServiceServer$MockClientHttpRequestFactory$1.executeInternal(MockRestServiceServer.java:289) at org.springframework.mock.http.client.MockClientHttpRequest.execute(MockClientHttpRequest.java:94) at org.springframework.mock.http.client.MockAsyncClientHttpRequest.executeAsync(MockAsyncClientHttpRequest.java:50) at org.springframework.web.client.AsyncRestTemplate.doExecute(AsyncRestTemplate.java:503) at org.springframework.web.client.AsyncRestTemplate.execute(AsyncRestTemplate.java:463) at org.springframework.web.client.AsyncRestTemplate.getForEntity(AsyncRestTemplate.java:217) at com.company.MainClient.getStatus(MainClient.java:151) at com.company.MainController.status(MainController.java:88)

The application aggregates data from several downstream systems. Requiring it to make several requests. Some of the requests are made asynchronously with the Future being handled later. Other requests block the main thread by immediately calling asyncRestTemplateResponse.get().

The following test causes the error:

Note: Server is MockRestServiceServer

@Test
public void statusTest() throws Exception {
    cServer.expect(once(),requestTo("http://localhost:8080/heartbeat"))
        .andRespond(withSuccess(cStatus, MediaType.APPLICATION_JSON));

    cpServer.expect(once(),requestTo("http://localhost:8081/status"))
            .andRespond(withSuccess(cpStatus, MediaType.APPLICATION_JSON));

    tServer.expect(once(),requestTo("http://localhost:3030/check"))
            .andRespond(withSuccess(tStatus, MediaType.TEXT_PLAIN));

    tServer.expect(once(),requestTo("http://localhost:3031/check"))
            .andRespond(withSuccess(tStatus, MediaType.TEXT_PLAIN));

    tServer.expect(once(),requestTo("http://localhost:3032/check"))
            .andRespond(withSuccess(tStatus, MediaType.TEXT_PLAIN));

    mockMvc.perform(get("/status").with(user(USERNAME).password(PASSWORD).roles("T_CLIENT")))
            .andDo(print()).andExpect(status().isOk())
            .andExpect(jsonPath("$.code").value("200"))
            .andExpect(jsonPath("$.appDescription").value("Main Service"))
            .andExpect(jsonPath("$.gateways[?(@.responseCode =~ /200/)]").isArray());

    //Test without basic auth
    mockMvc.perform(get("/status"))
            .andDo(print()).andExpect(status().isUnauthorized());
}
1 Answers
Related