I have a problem about Running Junit Service in my spring boot microservice example. I defined bearer token getting from /authenticate/login. It is valid. I can send a request to any service through it in Postman.
I cannot run the test method after copying baarer token and defining it here as shown below.
Here is the its test method
@DisplayName("Get Order - Success Scenario")
@Test
void test_When_Order_Success() {
String bearerToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJVc2VyIiwiaXNzIjoiUk9MRV9VU0VSICIsImlhdCI6MTY3MTQ4ODgyMiwiZXhwIjoxNjcxNDg4OTQyfQ.g83kKmFzDH539ZcpxM9D8bE_famFOevkOqNst_E8YG07b4yR4cEqcrySvz36vw8GJxTKm9gUQIM1J_G8cC5RGQ";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " bearerToken);
HttpEntity<String> request = new HttpEntity<String>(headers);
//Mocking
Order order = getMockOrder();
when(orderRepository.findById(anyLong()))
.thenReturn(Optional.of(order));
when(restTemplate.exchange(
"http://PRODUCT-SERVICE/product/" order.getProductId(),
HttpMethod.GET, request, ProductResponse.class).getBody()).thenReturn(getMockProductResponse());
when(restTemplate.exchange(
"http://PAYMENT-SERVICE/payment/order/" order.getId(),
HttpMethod.GET, request, PaymentResponse.class).getBody()).thenReturn(getMockPaymentResponse());
//Actual
OrderResponse orderResponse = orderService.getOrderDetails(1,bearerToken);
//Verification
verify(orderRepository, times(1)).findById(anyLong());
verify(restTemplate, times(1)).getForObject(
"http://PRODUCT-SERVICE/product/" order.getProductId(),
ProductResponse.class);
verify(restTemplate, times(1)).getForObject(
"http://PAYMENT-SERVICE/payment/order/" order.getId(),
PaymentResponse.class);
//Assert
assertNotNull(orderResponse);
assertEquals(order.getId(), orderResponse.getOrderId());
}
Here is the error shown below.
java.lang.NullPointerException: Cannot invoke "org.springframework.http.ResponseEntity.getBody()" because the return value of "org.springframework.web.client.RestTemplate.exchange(String, org.springframework.http.HttpMethod, org.springframework.http.HttpEntity, java.lang.Class, Object[])" is null
How can I fix the issue?
Here is the repo : Link
To run the app,
1 ) Run Service Registery (Eureka Server)
2 ) Run config server
3 ) Run zipkin and redis through these commands shown below on docker
docker run -d -p 9411:9411 openzipkin/zipkin
docker run -d --name redis -p 6379:6379 redis
4 ) Run api gateway
5 ) Run other services
CodePudding user response:
when(restTemplate.exchange( "http://PRODUCT-SERVICE/product/" order.getProductId(), HttpMethod.GET, request, ProductResponse.class).getBody()).thenReturn(getMockProductResponse()); when(restTemplate.exchange( "http://PAYMENT-SERVICE/payment/order/" order.getId(), HttpMethod.GET, request, PaymentResponse.class).getBody()).thenReturn(getMockPaymentResponse());
You would have to first mock restTemplate.exchange(...)
and return a mocked ResponseEntity
. Then you can mock responseEntity.getBody()
.
Please note that RestTemplate is deprecated and should be replaced with WebClient: https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/index.html?org/springframework/web/client/RestTemplate.html
In our project we're using the following best practice:
Wrap the RestTemplate/ WebClient with a Client component, which does not provide any business logic, just a nice API. We're testing this class with SpringBootTest and Wiremock. In the services we then can mock this custom client, which is much easier than mocking RestTemplate/ WebClient.
CodePudding user response:
Calling resttemplate
means you are doing an integration test. This also means you are loading all your spring
context and access your controller through a query you send with your resttemplate
and you don't need to mock your repository nor your service. You can only mock an external service while doing an integration or and end to end test.