Sping Boot 微服务JUnit测试- java.lang.NullPointerException异常:无法调用“组织.Spring框架.http.响应实体.getBody()”

nfs0ujit  于 2022-12-21  发布在  Java
关注(0)|答案(1)|浏览(198)

在我的spring Boot 微服务示例中,我遇到了一个关于在order服务中运行位于OrderServiceImplTest的名为test_When_Order_Success的测试方法的问题。
当我在获得一个不记名令牌后运行这个示例时,我遇到了如下所示的问题。

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
    at com.microservice.orderservice.service.OrderServiceImplTest.test_When_Order_Success(OrderServiceImplTest.java:70)

以下是所示的方法。

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

        String bearerToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJVc2VyIiwiaXNzIjoiUk9MRV9VU0VSICIsImlhdCI6MTY3MTM5NTQ0MCwiZXhwIjoxNjcxMzk1NTYwfQ.fBhI_flxuuXZfwhd8hEVdfkZkMNobVsi4hAdSXdl5qqWRedJWQWZXwYVdfSof6ezH7myZNQgn-kRNBXIDDHGDQ";

        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).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());
    }

编辑(我编辑了,但它没有帮助我解决这个问题。)

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()));
        // HERE IS THE ERROR
        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());

以下是错误消息

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
ProductResponse cannot be returned by exchange()
exchange() should return ResponseEntity
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
   Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - 
   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.

at com.microservice.orderservice.service.OrderServiceImplTest.test_When_Order_Success(OrderServiceImplTest.java:78)

如何解决此问题?
下面是github的回购协议:Link

要运行应用程序,

1)运行服务注册表(Eureka 服务器)
2)运行配置服务器
3)在docker上通过以下命令运行zipkin和redis

docker run -d -p 9411:9411 openzipkin/zipkin
  docker run -d --name redis -p 6379:6379 redis

4)运行API网关
5)运行其他服务

bz4sfanl

bz4sfanl1#

我们只模仿restTemplate,而不是任何形式的ResponseEntity

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
)

我甚至感到惊讶的是,这给了您一个NullPointerException,但不是任何类型的Mockito异常,因为您违反了模拟概念的最基本概念(您传递给when()的对象不是模拟)。
为了使其工作,将RestTemplate模拟传递给when,并将所需结果 Package 到ResponseEntity中以保留交换方法返回类型:

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();

相关问题