使用 @InjectMock 给 URI 不是绝对错误
Using @InjectMock giving URI not absolute error
我已经为使用 rest 模板调用另一个服务的方法编写了以下 Junit,但模拟抛出 URI not absolute 错误。
方法:
@Value("${app.prop.esso-url}")
private String essoUrl;
public ResponseEntity<String> essoCall(String token) {
ResponseEntity<String> response=null;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);
headers.setBearerAuth(token);
HttpEntity<String> entity = new HttpEntity<>(headers);
response= restTemplate.exchange(essoUrl, HttpMethod.GET, entity,String.class);
logger.info("successfully received response.");
return response;
}
单位:
@Autowired
private ObjectMapper objectMapper;
@InjectMocks
SecurityMsServiceImpl securityservice=new SecurityMsServiceImpl();
@Value("${app.prop.esso-url}")
private String essoUrl;
@Mock
private RestTemplate restTemplate;
@Test
void givenMockingIsDoneByMockito_whenGetIsCalled_shouldReturnMockedObject() {
ResponseEntity<String> responseEntity = new ResponseEntity<String>("success", HttpStatus.OK);
Mockito
.when(restTemplate.getForEntity(essoUrl
, String.class))
.thenReturn(responseEntity);
ResponseEntity<String> finalresponse=securityservice.essoCall("abc");
assertEquals(responseEntity, finalresponse);
}
我一次又一次看到这个问题:
您正在测试的方法中构建 RestTemplate
的新实例。
您应该做的是将它注入到您的 bean 中,这意味着:
- 在您的 bean 中添加一个类型为 RestTemplate 的字段
- 在构造函数中初始化它
- 在测试中,传入模拟实例
- 在产品中,通过 Spring DI
传入常规实例
RestTemplate 是线程安全的,它的一个实例是完全有效的。
参见 Is RestTemplate thread safe?
最重要的是:
- 我的建议是使用构造函数注入而不是字段注入
- 您正在混合使用 Spring 的 @Autowired 和 Mockito 的 @InjectMocks。选择是否要使用 MockitoExtension 或 SpringExtension 进行测试,并选择适当的一组注释来初始化您的 SUT。
我已经为使用 rest 模板调用另一个服务的方法编写了以下 Junit,但模拟抛出 URI not absolute 错误。
方法:
@Value("${app.prop.esso-url}")
private String essoUrl;
public ResponseEntity<String> essoCall(String token) {
ResponseEntity<String> response=null;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);
headers.setBearerAuth(token);
HttpEntity<String> entity = new HttpEntity<>(headers);
response= restTemplate.exchange(essoUrl, HttpMethod.GET, entity,String.class);
logger.info("successfully received response.");
return response;
}
单位:
@Autowired
private ObjectMapper objectMapper;
@InjectMocks
SecurityMsServiceImpl securityservice=new SecurityMsServiceImpl();
@Value("${app.prop.esso-url}")
private String essoUrl;
@Mock
private RestTemplate restTemplate;
@Test
void givenMockingIsDoneByMockito_whenGetIsCalled_shouldReturnMockedObject() {
ResponseEntity<String> responseEntity = new ResponseEntity<String>("success", HttpStatus.OK);
Mockito
.when(restTemplate.getForEntity(essoUrl
, String.class))
.thenReturn(responseEntity);
ResponseEntity<String> finalresponse=securityservice.essoCall("abc");
assertEquals(responseEntity, finalresponse);
}
我一次又一次看到这个问题:
您正在测试的方法中构建 RestTemplate
的新实例。
您应该做的是将它注入到您的 bean 中,这意味着:
- 在您的 bean 中添加一个类型为 RestTemplate 的字段
- 在构造函数中初始化它
- 在测试中,传入模拟实例
- 在产品中,通过 Spring DI 传入常规实例
RestTemplate 是线程安全的,它的一个实例是完全有效的。 参见 Is RestTemplate thread safe?
最重要的是:
- 我的建议是使用构造函数注入而不是字段注入
- 您正在混合使用 Spring 的 @Autowired 和 Mockito 的 @InjectMocks。选择是否要使用 MockitoExtension 或 SpringExtension 进行测试,并选择适当的一组注释来初始化您的 SUT。