簡體   English   中英

Spring Boot微服務-JUnit測試中RestTemplate空指針異常

[英]Spring Boot Microservices - RestTemplate Null Pointer Exception in JUnit Test

我在我的spring-boot微服務中運行 Junit 服務時遇到問題。 我定義了從/authenticate/login獲取的不記名令牌。 這是有效的。 我可以通過 Postman 向任何服務發送請求。

復制不記名令牌並在此處定義后,我無法運行測試方法,如下所示。

這是它的測試方法

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

這是下面顯示的錯誤。

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

我該如何解決這個問題?

這是回購協議:鏈接

要運行該應用程序,

  1. 運行服務注冊(尤里卡服務器)

  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. 運行其他服務

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

您必須首先模擬restTemplate.exchange(...)並返回模擬的ResponseEntity 然后你可以模擬responseEntity.getBody()

請注意,RestTemplate 已棄用,應替換為 WebClient: https ://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/index.html?org/springframework/web/client /RestTemplate.html

在我們的項目中,我們使用以下最佳實踐:

用一個客戶端組件包裝 RestTemplate/WebClient,它不提供任何業務邏輯,只是一個很好的 API。 我們正在使用 SpringBootTest 和 Wiremock 測試此類。 然后在服務中我們可以模擬這個自定義客戶端,這比模擬 RestTemplate/WebClient 容易得多。

您可以使用WireMock來模擬響應,而不是模擬該方法。 這可以使您的測試更加真實。

此外,調用RestTemplate意味着您正在進行集成測試。 這也意味着您正在加載所有spring上下文並通過您使用RestTemplate發送的查詢訪問您的控制器,並且您不需要模擬您的存儲庫或您的服務。 您只能在進行集成或端到端測試時模擬外部服務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM