0

这个问题已经被问过了。接受的答案对我不起作用。这是我的代码:-

我的服务在这里:

@Service
public class PlantService {

    @Autowired
    RestTemplate restTemplate;

    static String url = "http://some_url_?Combined_Name=Oak";

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }

    public String getJson() {
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
        return response.getBody();
    }
}

我的单元测试

@RunWith(SpringRunner.class)
class PlantServiceTest {

    private PlantService plantService;
    @Mock
    @Autowired
    private RestTemplate restTemplate;

    @Before
    void setUp() {
        MockitoAnnotations.initMocks(this);
        plantService = new PlantService();
    }

    @Test
    void testGetJsonString() {
        // arrange
        String expectedJson = "Some json string";
        ResponseEntity mocResponse = mock(ResponseEntity.class);

        // act
        when(restTemplate.getForEntity("url", String.class)).thenReturn(mocResponse);
        String actualJson = plantService.getJson();
        // assert
        assertSame(expectedJson, actualJson);
    }
}

当我调试并进入实际代码时。我可以看到 restTemplate 是 null 并且 throws java.lang.NullPointerException。那么如何对这段代码进行单元测试呢?

4

4 回答 4

0

你的问题是plantService = new PlantService();你从来没有注入这个 selft 创建的实例。

解决方案 1

我通常这样做:

@InjectMocks
private PlantService plantService = new PlantService();

@Mock
private RestTemplate restTemplate;

删除 setup 方法并使用 Mockito 而不是 SpringRunner 运行。

解决方案 2

如果您需要 SpringRunner,您可以执行以下操作:

@BeforeEach
void setUp() {
    MockitoAnnotations.initMocks(this);
    plantService = new PlantService();
    ReflectionTestUtils.setField(plantService, "restTemplate", restTemplate);
}

由于我在过去几年使用过 JUnit 5,因此我不确定 SpringRunner。在 JUnit 5 中,我可以同时使用这两个扩展(Spring 和 Mockito)。也许这也适用于 JUnit 4。

于 2020-06-03T12:28:02.327 回答
0

您可以执行以下操作:

  1. 删除@RunWith注释。

  2. @RestClientTest使用from注释您的测试类org.springframework.boot.test.autoconfigure.web.client.RestClientTest

  3. 使用MockRestServiceServerorg.springframework.test.web.client.MockRestServiceServer.

  4. 在测试方法中调用时模拟服务器的响应,例如:
@RestClientTest
public class MyTest {

  @Autowired
  private MockRestServiceServer server;

  public void test() {

    // setup
    String expected = "test_value";
    server.expect(requestToUriTemplate("/myendpoint"))
        .andRespond(withSuccess(myJsonResponse, MediaType.APPLICATION_JSON));

    // act
    String actual = myClient.fetch(myRequestDto);

    // assert
    assertThat(actual, equalTo(expected));
    server.verify();
  }
}

我正在使用assertThatfrom hamcrest,你可以使用任何你想断言结果正确性的东西。

于 2020-06-03T12:33:25.473 回答
0

您应该在PlantService. 例如:

public class PlantService {
  RestTemplate restTemplate;

  @Autowired
  public PlantService(RestTemplate restTemplate){
    this.restTemplate = restTemplate;
  }
}

在你的测试中,你可以这样做:

plantService = new PlantService(restTemplate);
                                   ^^
                                 yourMock
于 2020-06-03T12:33:29.520 回答
0

我已经尝试在我的机器上运行您的代码。

请找到测试运行测试类

@RunWith(SpringRunner.class)
class PlantServiceTest {

    @InjectMocks
    private PlantService plantService;

    @Mock
    private RestTemplate restTemplate;

    String url = "http://some_url_?Combined_Name=Oak";

    @BeforeEach
    void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    void testGetJsonString() {
        // arrange
        String expectedJson = "Some json string";
        ResponseEntity mocResponse = new ResponseEntity("Some json string", HttpStatus.OK);

        // act
        when(restTemplate.getForEntity(url, String.class)).thenReturn(mocResponse);
        String actualJson = plantService.getJson();
        // assert
        assertSame(expectedJson, actualJson);
    }
}
于 2020-06-05T05:26:52.880 回答