我想模拟属于我的类之一的 RestTemplate 实例变量的 postForEntity 方法,但它始终失败并出现“URI 不是绝对”错误,尽管我在其他示例中看到 anyString() 作为 URI 传入。需要注意的是,我没有@Mock my RestTemplate,因为我想测试它是否是由其父类的构造函数正确构建的(即超时)。
我无法发布实际代码,但我正在测试的类看起来像这样:
public class MyClient {
...
@Getter
@Setter
private RestTemplate restTemplate = new RestTemplate();
public MyClient(Property x, Property y, Property z){
this.x = x;
this.y = y;
this.z = z;
}
//New constructor that I want to test
public MyClient(Property x, Property y, Property z, int timeout){
this(x, y, z);
this.restTemplate =((SimpleClientHttpRequestFactory)getRestTemplate().getRequestFactory()).setReadTimeout(timeout);
}
public makeRequests() {
...
//myEndpoint, myRequest are assigned earlier in this fx, CustomResponse is a custom class
ResponseEntity resEntity = getRestTemplate().postForEntity(myEndpoint, myRequest, CustomResponse.class);
}
}
我想测试MyClient.restTemplate是否超时:
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest extends TestCase{
...
@Test
public void test_new_constructor(){
MyClient myClient = new MyClient(x, y, z, 1000);
RestTemplate restTemplate = myClient.getRestTemplate();
Mockito.when(restTemplate.postForEntity(anyString(), any(), any(Class.class))).thenAnswer(new AnswersWithDelay(100000, new Returns(new ResponseEntity(CustomResponse, HttpStatus.OK)) ));
//Will eventually add a delay to trigger a timeout + code for checking the exception, but it doesn't make it past the above line
myClient.makeRequests();
}
}
它在
Mockito.when(restTemplate.postForEntity(anyString(), any(), any(Class.class))).thenAnswer(new AnswersWithDelay(100000, new Returns(new ResponseEntity(CustomResponse, HttpStatus.OK)) ));
线上与 java.lang.IllegalArgumentException: URI is not absolute
失败,这是为什么?首先测试实际的 RestTemplate 是一个坏主意吗?我认为在网络调用上使用 Mockito.when
可以使测试不依赖于对实际端点的请求,但事实不是这样吗?
如果您没有模拟实例,则无法用它调用
when
。 when
保留用于模拟对象或间谍。
行
Mockito.when(restTemplate.postForEntity(anyString(), any(), any(Class.class)))
使用参数 postForEntity
调用真正的 anyString(), any(), any(Class.class)
方法,这实际上只是 "", null, null
:
ArgumentMatchers#anyString
:
public static String anyString() {
reportMatcher(new InstanceOf(String.class, "<any string>"));
return "";
}
#any
:
public static <T> T any() {
reportMatcher(Any.ANY);
return null;
}
空字符串
""
显然不是绝对URI。
如果你想测试一个类,你一定不能mock它;否则你只会测试模拟对象/模拟行为,而不是真正的类。
也就是说,我认为可以公平地假设
RestTemplate
已经被框架作者彻底测试过——为什么要测试它是否正确检测/触发超时? RestTemplate
的测试应该已经涵盖了这一点。
但是,如果您想测试您的应用程序代码是否正确处理
RestTemplate
的超时,那么请务必创建 RestTemplate
的模拟实例,将其设置为超时的行为,并验证您自己的代码是否可以处理模板的超时正确。