当我尝试模拟 RestTemplate.postForEntity() 时,为什么我的单元测试失败并显示“URI 不是绝对的”?

问题描述 投票:0回答:1

我想模拟属于我的类之一的 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
可以使测试不依赖于对实际端点的请求,但事实不是这样吗?

java mockito resttemplate
1个回答
0
投票

如果您没有模拟实例,则无法用它调用

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
的模拟实例,将其设置为超时的行为,并验证您自己的代码是否可以处理模板的超时正确。

© www.soinside.com 2019 - 2024. All rights reserved.