通过阅读,当您必须监视您正在单元测试的当前方法所使用的方法时,通常会出现不良做法和代码异味的迹象。
例如,我有这个正在单元测试的方法:
public MyResponseObject doStuff(MyRequestObject obj) {
WebTarget tar = getServiceClient().target(obj.toString());
Response res = tar.path(someURI).request().post(somejson);
if(response.getStatus() == 200) {
String jsonResp = response.readEntity(String.class);
return convertToObj(jsonResp);
}
}
我试图解决上述问题的一种方法是
- 将前两行(WebTarget、Response)提取到它自己的方法中,该方法返回一个 Response 对象。
- 创建 Response 的模拟并 stub readEntity 以返回 200 和 stub readEntity 以返回“OK”
结果如下:
public MyResponseObject doStuff(MyRequestObject obj) {
Response res = sendRequest(obj.toString());
if(response.getStatus() == 200) {
String jsonResp = response.readEntity(String.class);
return convertToObj(jsonResp);
}
}
//extracted method
public Response sendRequest(String json){
WebTarget tar = getServiceClient().target(someUrl);
return res = tar.path(someURI).request().post(somejson);
}
//My unit test
//sut is the system under test, setup elsewhere
public void testDoStuff() {
MyRequestObject request = ...;
Response respMock = mock(Response.class);
when(respMock.getStatus()).thenReturn(200);
when(respoMock.readEntity()).thenReturn("OK");
MyClass spy = spy(sut);
Mockito.doReturn(respMock).when(spy).sendRequest(requestString);
MyResponseObject response = spy.doStuff(request);
assertEquals(response.toString(),expectedResp);
}
如果我不把它 stub ,它会尝试做一个真正的 HTTP 请求并返回一个无效的 URL 错误,因为我没有提供一个真正的错误——我相信这就是我想要的,因为我希望我的单元测试是独立于一些外部系统。
有没有更好的方法来进行我的单元测试?
最佳答案
是的,创建一个你正在测试的类的 spy 是不好的做法,将你正在模拟的代码分解到另一个类中并模拟它,即:
public class MyClass {
private final MySender sender;
public MyClass() {
this(new DefaultSender());
}
public MyClass(MySender sender) {
this.sender = sender;
}
public MyResponseObject doStuff(MyRequestObject obj) {
Response res = sender.sendRequest(obj.toString());
if (response.getStatus() == 200) {
String jsonResp = response.readEntity(String.class);
return convertToObj(jsonResp);
}
}
public interface MySender {
Response sendRequest(String json);
}
private static class DefaultSender implements MySender {
public Response sendRequest(String json) {
WebTarget tar = getServiceClient().target(someUrl);
return res = tar.path(someURI).request().post(somejson);
}
}
}
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
private MyClass testSubject;
@Mock
private MySender sender;
@Mock
private Response response;
@Test
public void testDoStuff() {
String expectedResp = ...;
MyRequestObject request = ...;
MyResponseObject response = testSubject.doStuff(request);
assertEquals(response.toString(),expectedResp);
}
@Before
public void setup() {
testSubject = new MyClass(sender);
when(sender.sendRequest(anyString()).thenReturn(response);
when(response.getStatus()).thenReturn(200);
when(response.readEntity()).thenReturn("OK");
}
}
关于java - Mockito:监视被测系统中依赖于 HTTP 请求的方法是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53671685/