如何在单元测试中模拟 REST API?
How to Mock REST API in unit testing?
我正在使用 RestTemplate exchange HttpMethod.POST
方法 POST 到端点。在我的测试文件中,我正在测试 POST 方法的 success
。但是,在我当前的测试中,当发出 POST 请求时,我得到 401 Unauthorized error
。在测试文件
中发出 POST 请求时,我需要帮助来模拟 API
这是我的主文件
@Component
public class DataTestRepo {
private final RestTemplate restTemplate;
private final String url;
private final AllBuilder headersBuilder;
public DataTestRepo(
@Qualifier(Oauth.BEAN_NAME) AllBuilder headersBuilder,
RestTemplate restTemplate, String url) {
this.headersBuilder = headersBuilder;
this.restTemplate = restTemplate;
this.url = url;
}
public ResponseEntity<String> postJson(Set<String> results) {
ResponseEntity<String> result = null;
try {
JSONObject jsonObject = new JSONObject(body);
HttpEntity<String> request = new HttpEntity<String>(jsonObject.toString(), null);
restTemplate.getMessageConverters().add(stringConvertor);
result = restTemplate.exchange(url, HttpMethod.POST,
new HttpEntity<>(request, getHttpHeaders()), String.class);
}
return result;
}
}
这是我的测试文件
@RunWith(MockitoJUnitRunner.class)
@TestPropertySource
public class DataTestRepoTest {
private static final String url = "http://localhost:8080/data/name";
@Mock
private DataTestRepo DataTestRepo;
RestTemplate restTemplate = new RestTemplate();
@Test
public void restTemplateHttpPost_success() throws URISyntaxException {
URI uri = new URI(url);
Set<String> mockData = Stream.of("A","B").collect(Collectors.toSet());
Map<String, String> body = new HashMap<>();
body.put("Name", "Aws");
JSONObject jsonObject = new JSONObject(body);
HttpEntity<String> request = new HttpEntity<>(jsonObject.toString(), null);
ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST,
new HttpEntity<>(request, DataTestRepo.getHttpHeaders()), String.class);
Assert.assertEquals(201, result.getStatusCodeValue());
}
}
您正在测试 DataTestRepo class 中的逻辑,因此您不应该模拟它。
RestTemplate 是 DataTestRepo 内部的依赖项,因此这正是您需要模拟的。
一般来说,它在你的测试中应该是这样的:
@InjectMocks
private DataTestRepo DataTestRepo;
@Mock
RestTemplate restTemplate;
此外,您必须为模拟依赖项提供一个 return 值,如下所示:
Mockito.when(restTemplate.exchange(ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(new ResponseEntity<>(yourExpectedDataHere, HttpStatus.OK));
enter code here
这只是一个简单的例子。一个好的做法是检查传递给模拟的参数是否等于预期的参数。一种方法是用实际预期数据替换 ArgumentMatchers.any() 。另一种是单独验证,像这样:
Mockito.verify(restTemplate, Mockito.times(1)).exchange(ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere));
这是一本关于这个主题的好书:https://reflectoring.io/spring-boot-web-controller-test/
我正在使用 RestTemplate exchange HttpMethod.POST
方法 POST 到端点。在我的测试文件中,我正在测试 POST 方法的 success
。但是,在我当前的测试中,当发出 POST 请求时,我得到 401 Unauthorized error
。在测试文件
这是我的主文件
@Component
public class DataTestRepo {
private final RestTemplate restTemplate;
private final String url;
private final AllBuilder headersBuilder;
public DataTestRepo(
@Qualifier(Oauth.BEAN_NAME) AllBuilder headersBuilder,
RestTemplate restTemplate, String url) {
this.headersBuilder = headersBuilder;
this.restTemplate = restTemplate;
this.url = url;
}
public ResponseEntity<String> postJson(Set<String> results) {
ResponseEntity<String> result = null;
try {
JSONObject jsonObject = new JSONObject(body);
HttpEntity<String> request = new HttpEntity<String>(jsonObject.toString(), null);
restTemplate.getMessageConverters().add(stringConvertor);
result = restTemplate.exchange(url, HttpMethod.POST,
new HttpEntity<>(request, getHttpHeaders()), String.class);
}
return result;
}
}
这是我的测试文件
@RunWith(MockitoJUnitRunner.class)
@TestPropertySource
public class DataTestRepoTest {
private static final String url = "http://localhost:8080/data/name";
@Mock
private DataTestRepo DataTestRepo;
RestTemplate restTemplate = new RestTemplate();
@Test
public void restTemplateHttpPost_success() throws URISyntaxException {
URI uri = new URI(url);
Set<String> mockData = Stream.of("A","B").collect(Collectors.toSet());
Map<String, String> body = new HashMap<>();
body.put("Name", "Aws");
JSONObject jsonObject = new JSONObject(body);
HttpEntity<String> request = new HttpEntity<>(jsonObject.toString(), null);
ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST,
new HttpEntity<>(request, DataTestRepo.getHttpHeaders()), String.class);
Assert.assertEquals(201, result.getStatusCodeValue());
}
}
您正在测试 DataTestRepo class 中的逻辑,因此您不应该模拟它。 RestTemplate 是 DataTestRepo 内部的依赖项,因此这正是您需要模拟的。 一般来说,它在你的测试中应该是这样的:
@InjectMocks
private DataTestRepo DataTestRepo;
@Mock
RestTemplate restTemplate;
此外,您必须为模拟依赖项提供一个 return 值,如下所示:
Mockito.when(restTemplate.exchange(ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(new ResponseEntity<>(yourExpectedDataHere, HttpStatus.OK));
enter code here
这只是一个简单的例子。一个好的做法是检查传递给模拟的参数是否等于预期的参数。一种方法是用实际预期数据替换 ArgumentMatchers.any() 。另一种是单独验证,像这样:
Mockito.verify(restTemplate, Mockito.times(1)).exchange(ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere), ArgumentsMatchers.eq(yourExpectedDataHere));
这是一本关于这个主题的好书:https://reflectoring.io/spring-boot-web-controller-test/