skip to Main Content

I have a problem about running the test method named test_When_Order_Success located at OrderServiceImplTest in order service in my spring boot microservice example.

When I run the example after getting a bearer token, I get this issue shown below.

Here is the method shown below.

@DisplayName("Get Order - Success Scenario")
    @Test
    void test_When_Order_Success() {

        String bearerToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJVc2VyIiwiaXNzIjoiUk9MRV9VU0VSICIsImlhdCI6MTY3MjQ0Mjg3NywiZXhwIjoxNjcyNDQyOTk3fQ.O6Rm41kFN8SBNUVAiKrsM4O_PBI5qurpmSU34AEk5RTT3ZkPoxiFGeI0byrHOBPPOgyVRXxY_KhgzPcKKgm1ew";

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer "+ bearerToken);

        HttpEntity request = new HttpEntity<>(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)).thenReturn(ResponseEntity.ok(getMockProductResponse()));

        when(restTemplate.exchange(
                "http://PAYMENT-SERVICE/payment/order/" + order.getId(),
                HttpMethod.GET, request, PaymentResponse.class)).thenReturn(ResponseEntity.ok(getMockPaymentResponse()));

        //Actual
        OrderResponse orderResponse = orderService.getOrderDetails(1,bearerToken);

        //Verification
        verify(orderRepository, times(1)).findById(anyLong());

        verify(restTemplate, times(1))
                .exchange("http://PRODUCT-SERVICE/product/" + order.getProductId(), HttpMethod.GET,
                request, ProductResponse.class);

        verify(restTemplate, times(1))
                .exchange("http://PAYMENT-SERVICE/payment/order/" + order.getId(), HttpMethod.GET,
                request, PaymentResponse.class);

        //Assert
        assertNotNull(orderResponse);
        assertEquals(order.getId(), orderResponse.getOrderId());
    }

Here is the error message

02:28:15.051 [main] INFO com.microservice.orderservice.service.impl.OrderServiceImpl - OrderServiceImpl | getOrderDetails | Get order details for Order Id : 1
02:28:15.056 [main] INFO com.microservice.orderservice.service.impl.OrderServiceImpl - OrderServiceImpl | getOrderDetails | Invoking Product service to fetch the product for id: 1

org.mockito.exceptions.misusing.PotentialStubbingProblem: 
Strict stubbing argument mismatch. Please check:
 - this invocation of 'exchange' method:
    restTemplate.exchange(
    "http://PRODUCT-SERVICE/product/1",
    GET,
    <[Content-Type:"application/json", Authorization:"eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJVc2VyIiwiaXNzIjoiUk9MRV9VU0VSICIsImlhdCI6MTY3MjQ0Mjg3NywiZXhwIjoxNjcyNDQyOTk3fQ.O6Rm41kFN8SBNUVAiKrsM4O_PBI5qurpmSU34AEk5RTT3ZkPoxiFGeI0byrHOBPPOgyVRXxY_KhgzPcKKgm1ew"]>,
    class com.microservice.orderservice.payload.response.ProductResponse
);
    -> at com.microservice.orderservice.service.impl.OrderServiceImpl.getOrderDetails(OrderServiceImpl.java:113)
 - has following stubbing(s) with different arguments:
    1. restTemplate.exchange(
    "http://PRODUCT-SERVICE/product/1",
    GET,
    <[Content-Type:"application/json", Authorization:"Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJVc2VyIiwiaXNzIjoiUk9MRV9VU0VSICIsImlhdCI6MTY3MjQ0Mjg3NywiZXhwIjoxNjcyNDQyOTk3fQ.O6Rm41kFN8SBNUVAiKrsM4O_PBI5qurpmSU34AEk5RTT3ZkPoxiFGeI0byrHOBPPOgyVRXxY_KhgzPcKKgm1ew"]>,
    class com.microservice.orderservice.payload.response.ProductResponse
);
      -> at com.microservice.orderservice.service.OrderServiceImplTest.test_When_Order_Success(OrderServiceImplTest.java:71)
    2. restTemplate.exchange(
    "http://PAYMENT-SERVICE/payment/order/1",
    GET,
    <[Content-Type:"application/json", Authorization:"Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJVc2VyIiwiaXNzIjoiUk9MRV9VU0VSICIsImlhdCI6MTY3MjQ0Mjg3NywiZXhwIjoxNjcyNDQyOTk3fQ.O6Rm41kFN8SBNUVAiKrsM4O_PBI5qurpmSU34AEk5RTT3ZkPoxiFGeI0byrHOBPPOgyVRXxY_KhgzPcKKgm1ew"]>,
    class com.microservice.orderservice.payload.response.PaymentResponse
);
      -> at com.microservice.orderservice.service.OrderServiceImplTest.test_When_Order_Success(OrderServiceImplTest.java:75)
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
However, there are legit scenarios when this exception generates false negative signal:
  - stubbing the same method multiple times using 'given().will()' or 'when().then()' API
    Please use 'will().given()' or 'doReturn().when()' API for stubbing.
  - stubbed method is intentionally invoked with different arguments by code under test
    Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).
For more information see javadoc for PotentialStubbingProblem class.

    at com.microservice.orderservice.service.impl.OrderServiceImpl.getOrderDetails(OrderServiceImpl.java:113)
    at com.microservice.orderservice.service.OrderServiceImplTest.test_When_Order_Success(OrderServiceImplTest.java:94)

How can I fix the issue?

Here is the github 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

2

Answers


  1. You only mock restTemplate, but not ResponseEntity of any form. So what you basically do:

    when(
        mock.method() // returns ResponseEntity, which is always null, unless mocked previously
            .method() // a method call on an object, which is not even a mock
    )
    

    I am even surpised this gives you a NullPointerException, but not a Mockito exception of any kind as you violate the very basics of the mock concept (the object you pass to when() is not a mock).

    In order to make it work pass the RestTemplate mock to when, and wrap the desired result into a ResponseEntity to preserve the exchange method return type:

            when(restTemplate.exchange(
                "http://PRODUCT-SERVICE/product/" + order.getProductId(),
                HttpMethod.GET, request, ProductResponse.class))
            .thenReturn(ResponseEntity.ok(getMockProductResponse()));
    
            when(restTemplate.exchange(
                "http://PAYMENT-SERVICE/payment/order/" + order.getId(),
                HttpMethod.GET, request, PaymentResponse.class))
            .thenReturn(ResponseEntity.ok(getMockPaymentResponse()));
    
            OrderResponse orderResponse = orderService.getOrderDetails(1, bearerToken).getBody();
    
    Login or Signup to reply.
  2. First of all, you should use @ExtendWith(MockitoExtension.class) instead of @SprintBootTest on the test class since you are not doing integration test and using JUnit5 with Mockito.

    Secondly, there is no ‘Bearer ‘ prefix on your Authorization header token in your OrderServiceImpl.

    And you do not need to mock getBody() of ResponseEntity since you already mock restTemplate.exchange().

    Lastly, the method you are verifying should be exchange() not getForObject().

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search