mockito 为什么我的单元测试失败了“URI不是绝对的”,当我试图模仿RestTemplate.postForEntity()?

r7xajy2e  于 2023-11-18  发布在  其他
关注(0)|答案(1)|浏览(192)

我想模拟属于我的一个类的RestTemplate示例变量的postForEntity方法,但它总是失败,并出现“URI不是绝对的”错误,尽管我在其他示例中看到anyString()作为URI传入。应该注意的是,我没有@Mock我的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会使测试不依赖于对实际端点的请求,但事实并非如此?

jyztefdp

jyztefdp1#

如果你没有模拟过一个示例,你不能用它调用whenwhen是为模拟对象或间谍保留的。
Mockito.when(restTemplate.postForEntity(anyString(), any(), any(Class.class)))调用了带有参数anyString(), any(), any(Class.class)的真实的postForEntity方法,它实际上就是"", 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。
如果你想测试一个类,你不能模拟它;否则你只会测试模拟对象/模拟行为,而不是你的真实的类。
也就是说,我认为可以假设RestTemplate已经被框架作者彻底测试过了-为什么你想测试它是否正确检测/触发超时?这应该已经被RestTemplate的测试所覆盖。
但是,如果您想测试您的应用程序代码是否正确处理了RestTemplate的超时,那么无论如何都要创建RestTemplate的模拟示例,将其设置为超时的行为,并验证您自己的代码是否正确处理了模板的超时。

相关问题