如何使用mockito模拟Spring RestTemplate?
实际上,我正在尝试使用下面的方法:如何使用mockito模拟Spring RestTemplate?,spring,spring-boot,mockito,spring-test,Spring,Spring Boot,Mockito,Spring Test,实际上,我正在尝试使用下面的方法: @Override public Reservation findReservation(Long id) { RestTemplate restTemplate = new RestTemplate(); Reservation reservation = restTemplate.getForObject(RESERVATION_REST_URL+id, Reservation.class); return reservat
@Override
public Reservation findReservation(Long id) {
RestTemplate restTemplate = new RestTemplate();
Reservation reservation = restTemplate.getForObject(RESERVATION_REST_URL+id, Reservation.class);
return reservation;
}
我正在做UT,如下所示:
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
@Test
public void testFindReservation(){
Reservation reservation = new Reservation();
reservation.setId(1000l);
reservation.setCheckiIn(true);
reservation.setNumberOfBags(10);
when(restTemplate.getForObject("http://localhost:8080/flightreservation/reserva
tions/1000", Reservation.class))
.thenReturn(reservation);
Reservation res = reservationRestClient.findReservation(1000l);
Assert.assertNotNull(res);
}
但它给出了错误,根据我的理解,它没有正确地模拟,不知何故RestTemplate试图调用真正的api而不是模拟
ResourceAccessException: I/O error on GET request for http://localhost:8080/flightreservation/reserva
tions/1000
服务类别:-
@Service
public class ReservationRestServiceImpl implements ReservationRestService {
private static final String RESERVATION_REST_URL = "http://localhost:8080/flightreservation/reservations/";
private final RestTemplate restTemplate;
public ReservationRestServiceImpl(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
@Override
public Reservation fetchReservationByPnr(Long id) {
Reservation reservation = restTemplate.getForObject(RESERVATION_REST_URL+id, Reservation.class);
return reservation;
}
}
测试文件如下,在测试文件中模拟RestTemplateBuilder后,它给出NLP
@RunWith(SpringRunner.class)
//@AutoConfigureWebClient
@SpringBootTest(classes = { WebcheckinApplication.class })
public class WebcheckinApplicationTests {
private ReservationRestServiceImpl reservationRestServiceImpl;
@Mock
private RestTemplateBuilder restTemplateBuilder;
@Before
public void setUp() throws Exception {
reservationRestServiceImpl = new ReservationRestServiceImpl();
MockitoAnnotations.initMocks(this);
}
@Test
public void contextLoads() {
}
@Test
public void testFindReservation(){
Reservation reservation = new Reservation();
reservation.setId(1000l);
reservation.setCheckiIn(true);
reservation.setNumberOfBags(10);
RestTemplateBuilder builder = mock(RestTemplateBuilder.class);
reservationRestServiceImpl.setBuilder(builder);
reservationRestServiceImpl.init();
when(builder.build().getForObject("http://localhost:8080/flightreservation/reservations/1000", Reservation.class))
.thenReturn(reservation);
Reservation res = reservationRestServiceImpl.fetchReservationByPnr(1000l);
Assert.assertNotNull(res);
//assertEquals("{message : 'under construction'}", result);
}
}
我不确定您使用的是哪个版本的Spring。但是,Spring中推荐的模式是使用RestTemplateBuilder,而不是直接创建RestTemplate RestTemplateBuilder将被注入到服务中,rest模板将由此构建。在您的测试用例中,您可以注入一个模拟的RestTemplateBuilder,它反过来可以返回一个模拟的RestTemplate 因此,如果您能够重构原始服务,那么您可以拥有一些更易于测试的代码 --更多细节-- 这就是我如何设置班级的方法
public class SomeService {
private RestTemplateBuilder builder;
private RestTemplate restTemplate;
@Autowired
public void setBuilder(RestTemplateBuilder builder) {
this.builder = builder;
}
@PostConstruct
public void init() {
restTemplate = builder.build();
}
public Object fetchReservationByPnr(Long id) {
return restTemplate.getForObject("someUrl"+id, Object.class);
}
}
然后,在测试中,您可以创建服务,分配模拟的RestTemplateBuilder并调用init。您不需要Spring runner,也不需要在Spring上下文中运行测试。标准的JUnit runner就足够了
我还没有完全完成你的测试,但这对我来说很有效
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.web.client.RestTemplate;
public class SomeServiceTest {
@Test
public void testMe() {
RestTemplateBuilder mockedBuilder = Mockito.mock(RestTemplateBuilder.class);
RestTemplate mockedRestTemplate = Mockito.mock(RestTemplate.class);
Mockito.when(mockedBuilder.build()).thenReturn(mockedRestTemplate);
SomeService someService = new SomeService();
someService.setBuilder(mockedBuilder);
someService.init();
Mockito.verify(mockedBuilder).build();
}
}
对于您的测试,只需将其他模拟添加到模拟的RestTemplate
@Sandeep Tiwari..将您的测试用例设置为这样
嗨@EdH我现在已经更新了源代码,但是它给出了NLPYes,我看到了更新。但是,测试代码不应该构造rest模板。我会把更多的细节放在我的回答上面,请在测试电话中帮忙,实际上我仍然面临同样的问题NLP,实际上我已经在测试文件和setBuilder中与您的更改和自动连线服务保持一致。更新的测试文件也给了我NLP,在模拟之后,不知何故无法模拟RestTemplateBuilder。嗨@SandeptiWari,我已经在中添加了一些详细信息。请参考我是如何做测试的。这对我在当地很管用。
@Autowired
private MockRestServiceServer server;
@Autowired
private RestTemplate restTemplate;
add these following in @Before method ....
------------------------------------
server.expect(ExpectedCount.manyTimes(), requestTo(URL)).andRespond(withSuccess(detailsString, MediaType.APPLICATION_JSON));