Как создать окончательный новый экземпляр RestTemplate с помощью Mockito

#java #unit-testing #junit #mockito

#java #модульное тестирование #junit #mockito

Вопрос:

 Component
public class MyService {
  private final ObjectMapper objectMapper = new ObjectMapper();
  private final RestTemplate restTemplate = new RestTemplate();

  public void myMethod(){
      

    ------- codes to test above it------ 
     
     HttpEntity<String> httpEntity = new HttpEntity<>(objectMapper
          .writeValueAsString(message), httpHeaders);
      String response = restTemplate
          .postForObject(getUrl(), httpEntity, String.class);

  }

}
 

Я пробовал @Spy, но он не работает

 @InjectMocks
  private MyService myService;
  
  @Spy
  private RestTemplate restTemplate;


 when(restTemplate.postForObject(
    getUrl(),
    httpEntity,
    String.class
)).thenReturn(getResponse());
 

Комментарии:

1. Неужели это весна?

2. Вы можете написать защищенный конструктор для MyService, который принимает параметр RestTemplate.

3. Да, это весной

Ответ №1:

Если вы хотите шпионить:

 @Test
void test(){
    MyService myService = Mockito.spy(MyService.class);
    myService.myMethod();
}
 

Таким образом, вы получаете экземпляр RestTemplate.

Лично я предпочитаю получать RestTemplate в качестве зависимости, которая позволяет легко издеваться.

например:

 private final RestTemplate restTemplate;

public MyService(RestTemplate restTemplate) {
    this.restTemplate = restTemplate;
}
 

И в вашем тесте

 //@RunWith(MockitoJUnitRunner.class) //junit4
@ExtendWith(MockitoExtension.class) //junit 5
public class MyServiceTest {

@Mock
private RestTemplate restTemplate;

@InjectMocks
private MyService myService;

@Test
void test(){
    when(restTemplate.postForObject(
            getUrl(),
            httpEntity,
            String.class
    )).thenReturn(getResponse());
    //do whatever you like
   }

}
 

Комментарии:

1. Я хочу издеваться над методом postForObject, а не вызывать фактический метод

2. Вы пытаетесь протестировать myMethod(), не так ли?

3. о, пропустил деталь, я хочу протестировать приведенный выше код, чтобы он не вызывал фактический http-вызов, отредактировал мой код

Ответ №2:

spring-boot-test предоставляет хороший способ имитировать компоненты с помощью аннотаций MockBean и SpyBean.

Попробуйте использовать @SpyBean вместо @Spy и @MockBean вместо @Mock .

 @MockBean
private RestTemplate restTemplate
 

В этом случае ничего не @InjectMocks требуется.