模拟 RestTemplate API 调用
Mock RestTemplate API call
我需要对使用 RestTemplate 进行外部 API 调用的方法进行单元测试,为此我试图模拟外部 API 的响应并断言 return方法的价值。我还尝试使用 MockRestServiceServer
和 @InjectMocks
来模拟响应,但无法获得预期的输出,它进行了实际的 API 调用。任何指导将不胜感激。
测试用例
public class SnowFlakeServiceTest {
private final RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
private final SnowFlakeServiceImpl snowFlakeService = new SnowFlakeServiceImpl(restTemplate);
@Test
public void testGetAccessToken() {
SnowFlakeTokenDTO snowFlakeTokenDTO = new SnowFlakeTokenDTO();
snowFlakeTokenDTO.setAccessToken("fakeAccessToken");
snowFlakeTokenDTO.setExpiresIn(600);
snowFlakeTokenDTO.setTokenType("Bearer");
ResponseEntity<SnowFlakeTokenDTO> responseEntity = new ResponseEntity<>(snowFlakeTokenDTO, HttpStatus.OK);
when(restTemplate.exchange(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.<Class<SnowFlakeTokenDTO>>any()))
.thenReturn(responseEntity);
assertThat(snowFlakeService.getAccessToken()).isEqualTo(snowFlakeTokenDTO.getAccessToken());
}
}
SnowFlakeServiceImpl.java
private final RestTemplate restTemplate;
public SnowFlakeServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public String getAccessToken() {
log.debug("token requested id : {}, secret :{}", snowFlakeClientId, snowFlakeClientSecret);
try {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
httpHeaders.setBasicAuth(snowFlakeClientId, snowFlakeClientSecret);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("grant_type", snowFlakeRefreshTokenGrantType);
requestBody.add("refresh_token", refreshToken);
requestBody.add("redirect_uri", snowFlakeRedirectUrl);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestBody, httpHeaders);
ResponseEntity<SnowFlakeTokenDTO> response = restTemplate.exchange(snowFlakeTokenRequestUrl, HttpMethod.POST, request, SnowFlakeTokenDTO.class);
log.debug("response: {}", response);
return Objects.requireNonNull(response.getBody()).getAccessToken();
} catch (Exception e) {
log.debug("error: {}", ExceptionUtils.getRootCauseMessage(e));
throw new ErrorDTO(Status.BAD_REQUEST, accessTokenErrorMessage, e.getMessage());
}
}
RestTemplateConigurations.java
@Configuration
public class RestTemplateConfiguration {
@Value("${rest-template.connection.timeout}")
private int connectionTimeout;
@Value("${rest-template.read.timeout}")
private int readTimeout;
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofMillis(connectionTimeout))
.setReadTimeout(Duration.ofMillis(readTimeout))
.build();
}
}
Spring 引导:2.5.4
Java : 11
单位:5
每次调用 getAccessToken()
方法时,您不需要新的 RestTemplate
。它应该由 Spring:
注入
@Service
public class SnowFlakeService {
private RestTemplate restTemplate;
public ServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public String getAccessToken() {
try {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
httpHeaders.setBasicAuth(snowFlakeClientId, snowFlakeClientSecret);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("grant_type", snowFlakeRefreshTokenGrantType);
requestBody.add("refresh_token", refreshToken);
requestBody.add("redirect_uri", snowFlakeRedirectUrl);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestBody, httpHeaders);
ResponseEntity<SnowFlakeTokenDTO> response = restTemplate.exchange(snowFlakeTokenRequestUrl, HttpMethod.POST, request, SnowFlakeTokenDTO.class);
return Objects.requireNonNull(response.getBody()).getAccessToken();
} catch (Exception e) {
throw new ErrorDTO(Status.BAD_REQUEST, accessTokenErrorMessage, e.getMessage());
}
}
}
除此之外,您实际上不需要 @SpringBootTest
来测试 SnowFlakeService
。常规单元测试就可以了。
public class SnowFlakeServiceTest {
private RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
private SnowFlakeService snowFlakeService = new SnowFlakeService(restTemplate);
@Test
public void testGetAccessToken() {
SnowFlakeTokenDTO snowFlakeTokenDTO = new SnowFlakeTokenDTO();
snowFlakeTokenDTO.setAccessToken("fakeAccessToken");
snowFlakeTokenDTO.setExpiresIn(600);
snowFlakeTokenDTO.setTokenType("Bearer");
ResponseEntity<SnowFlakeTokenDTO> responseEntity = new ResponseEntity<>(snowFlakeTokenDTO, HttpStatus.OK);
when(restTemplate.exchange(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.<Class<SnowFlakeTokenDTO>>any()))
.thenReturn(responseEntity);
assertThat(snowFlakeService.getAccessToken()).isEqualTo(snowFlakeTokenDTO.getAccessToken());
}
}
我需要对使用 RestTemplate 进行外部 API 调用的方法进行单元测试,为此我试图模拟外部 API 的响应并断言 return方法的价值。我还尝试使用 MockRestServiceServer
和 @InjectMocks
来模拟响应,但无法获得预期的输出,它进行了实际的 API 调用。任何指导将不胜感激。
测试用例
public class SnowFlakeServiceTest {
private final RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
private final SnowFlakeServiceImpl snowFlakeService = new SnowFlakeServiceImpl(restTemplate);
@Test
public void testGetAccessToken() {
SnowFlakeTokenDTO snowFlakeTokenDTO = new SnowFlakeTokenDTO();
snowFlakeTokenDTO.setAccessToken("fakeAccessToken");
snowFlakeTokenDTO.setExpiresIn(600);
snowFlakeTokenDTO.setTokenType("Bearer");
ResponseEntity<SnowFlakeTokenDTO> responseEntity = new ResponseEntity<>(snowFlakeTokenDTO, HttpStatus.OK);
when(restTemplate.exchange(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.<Class<SnowFlakeTokenDTO>>any()))
.thenReturn(responseEntity);
assertThat(snowFlakeService.getAccessToken()).isEqualTo(snowFlakeTokenDTO.getAccessToken());
}
}
SnowFlakeServiceImpl.java
private final RestTemplate restTemplate;
public SnowFlakeServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public String getAccessToken() {
log.debug("token requested id : {}, secret :{}", snowFlakeClientId, snowFlakeClientSecret);
try {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
httpHeaders.setBasicAuth(snowFlakeClientId, snowFlakeClientSecret);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("grant_type", snowFlakeRefreshTokenGrantType);
requestBody.add("refresh_token", refreshToken);
requestBody.add("redirect_uri", snowFlakeRedirectUrl);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestBody, httpHeaders);
ResponseEntity<SnowFlakeTokenDTO> response = restTemplate.exchange(snowFlakeTokenRequestUrl, HttpMethod.POST, request, SnowFlakeTokenDTO.class);
log.debug("response: {}", response);
return Objects.requireNonNull(response.getBody()).getAccessToken();
} catch (Exception e) {
log.debug("error: {}", ExceptionUtils.getRootCauseMessage(e));
throw new ErrorDTO(Status.BAD_REQUEST, accessTokenErrorMessage, e.getMessage());
}
}
RestTemplateConigurations.java
@Configuration
public class RestTemplateConfiguration {
@Value("${rest-template.connection.timeout}")
private int connectionTimeout;
@Value("${rest-template.read.timeout}")
private int readTimeout;
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofMillis(connectionTimeout))
.setReadTimeout(Duration.ofMillis(readTimeout))
.build();
}
}
Spring 引导:2.5.4
Java : 11
单位:5
每次调用 getAccessToken()
方法时,您不需要新的 RestTemplate
。它应该由 Spring:
@Service
public class SnowFlakeService {
private RestTemplate restTemplate;
public ServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public String getAccessToken() {
try {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
httpHeaders.setBasicAuth(snowFlakeClientId, snowFlakeClientSecret);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("grant_type", snowFlakeRefreshTokenGrantType);
requestBody.add("refresh_token", refreshToken);
requestBody.add("redirect_uri", snowFlakeRedirectUrl);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestBody, httpHeaders);
ResponseEntity<SnowFlakeTokenDTO> response = restTemplate.exchange(snowFlakeTokenRequestUrl, HttpMethod.POST, request, SnowFlakeTokenDTO.class);
return Objects.requireNonNull(response.getBody()).getAccessToken();
} catch (Exception e) {
throw new ErrorDTO(Status.BAD_REQUEST, accessTokenErrorMessage, e.getMessage());
}
}
}
除此之外,您实际上不需要 @SpringBootTest
来测试 SnowFlakeService
。常规单元测试就可以了。
public class SnowFlakeServiceTest {
private RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
private SnowFlakeService snowFlakeService = new SnowFlakeService(restTemplate);
@Test
public void testGetAccessToken() {
SnowFlakeTokenDTO snowFlakeTokenDTO = new SnowFlakeTokenDTO();
snowFlakeTokenDTO.setAccessToken("fakeAccessToken");
snowFlakeTokenDTO.setExpiresIn(600);
snowFlakeTokenDTO.setTokenType("Bearer");
ResponseEntity<SnowFlakeTokenDTO> responseEntity = new ResponseEntity<>(snowFlakeTokenDTO, HttpStatus.OK);
when(restTemplate.exchange(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.<Class<SnowFlakeTokenDTO>>any()))
.thenReturn(responseEntity);
assertThat(snowFlakeService.getAccessToken()).isEqualTo(snowFlakeTokenDTO.getAccessToken());
}
}