1

I am developing a Spring Boot application/library where i have a Service that sends a request to a an API. When in integration Test the Entry Point into the Service is an /integration Endpoint. The following Code is the mvp to reproduce the error

Main Service:

@Service
@RequiredArgsConstructor
public class CalculationService {

  private final RestClient restClient;

  public CalculationResponse calculate(CalculationRequest request){
    return restClient.post().uri("/service/calculate")
        .body(request)
        .retrieve()
        .toEntity(CalculationResponse.class).getBody();

  }
}

Main Controller

@RestController
@RequestMapping("/service")
public class MockApi {


  @PostMapping("/calculate")
  public CalculationResponse calculate(@RequestBody CalculationRequest calculationRequest) {
    CalculationResponse calculationResponse = new CalculationResponse();
    calculationResponse.setSummary(calculationRequest.getName()+ "----" + calculationRequest.getValue());
    return calculationResponse;
  }
}

The Entry Point for my Integration Test

@RestController
@RequestMapping
@RequiredArgsConstructor
public class TestController {

  private final CalculationService calculationService;

  @PostMapping("/integration")
  public CalculationResponse integration(@RequestBody CalculationRequest request) {
    return calculationService.calculate(request);
  }

}

RestClient Configuration

@Configuration
public class CalculationConfiguration {


  @Bean
  public RestClient restClient() {
    return RestClient.builder()
        .baseUrl("http://localhost:8080")
        .build();
  }

}

Integration Test

@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ExtendWith(SpringExtension.class)
public class IntegrationTest {

  @Autowired
  private MockMvc mockMvc;

  @Autowired
  private ObjectMapper objectMapper;

  @Test
  public void thatSummaryIsReturned() throws Exception {

    CalculationRequest request = new CalculationRequest("Test", "Value");
    mockMvc.perform(MockMvcRequestBuilders.post("/integration")
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(request)))
        .andExpect(status().isOk())
        .andReturn();
  }

}

When running the test i receive following error:

Request processing failed: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:8080/service/calculate": null jakarta.servlet.ServletException: Request processing failed: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:8080/service/calculate": null at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1022) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72) at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)

When i change the endpoint in my integration test directly to /service/calculate it works. I tried to debug but when having /integration as path in the test i dont even react the other endpoint. Has anyone an idea why this is the case ?

Edit: When the Application runs in the Background it works. So it seems that there is something missing in my TestContext ...

4
  • pls add your integration test code Commented Mar 14 at 20:39
  • Added the test code. The whole sourcecode is here: github.com/bonbonn1912/mock-mvc-error this is a repository to reproduce the error. Commented Mar 14 at 20:39
  • And this only happens when the restclient performs a request to an internal controller. So when going to an external endpoint it works. The TestController Bean is also in the ApplicationContext and works when the mockmvc directly calls it ... Commented Mar 14 at 20:44
  • If this is a full on integration test, provide a way to pass the port when creating your RestClient and pass it through your test configuration. Commented Mar 14 at 22:11

1 Answer 1

2

The issue occurs because you are using @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT), which starts your application on a random port. However, your RestClient is explicitly configured to use http://localhost:8080, leading to a port mismatch. Since the application is not actually running on port 8080 during the test, requests fail with an I/O error when trying to reach http://localhost:8080/service/calculate.

One solution is to start the test on a defined port:

@SpringBootTest(
     webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, 
     properties = "server.port=8080"
)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.