我正在编写测试套件,我正在思考如何模拟某些请求/响应流程。例如,我想测试一个进行多个RESTful调用的方法:
getCounts() {
...
Promise<Integer> count1 = getCount1();
Promise<Integer> count2 = getCount2();
// returns a DataModel containing all counts when the Promises redeem
}
getCount1() {
...
Request<Foo> request = new Request<Foo>();
sendRequest(request);
...
}
getCount2() {
...
Request<Bar> request = new Request<Bar>();
sendRequest(request);
...
}
sendRequest(Request<T> request) {...}
但是,每个getCount()
方法都会创建一个不同的Request<T>
对象,其中<T>
描述了正在检索的计数的请求类型。这意味着我不能简单地&#34;模拟&#34; sendRequest()
方法,因为每次都使用不同的类型调用它。
我正在考虑一种方法,我注册一个&#34;处理程序&#34; ...当调用sendRequest()
时,它确定要调用哪个处理程序,并且处理程序将知道适当的mock类型要返回的数据。注册将类似于存储处理程序类类型或处理程序类的实例以及它所需的模拟数据,并且在调用sendRequest()
时,它将查找并调用正确的处理程序。
但是,我不确定这是否是一个好的模式,我想知道是否有更好的方法来解决这个问题。注册类或特定方法以便稍后执行特定任务的好模式是什么?
答案 0 :(得分:1)
没有更多上下文很难回答,但一般的方法是使用控制反转(IOC)。例如,将getCountXXX
方法放入自己的类中,这可能是更好的重用,可读性,封装,可测试性等的好主意:
public class CountFetcher {
getCount1() { ... }
getCount2() { ... }
}
原始代码现在使用您可以使用的“注入”机制获取CountFetcher
的实例。最简单的只是一个构造函数:
public class Counter {
private final CountFetcher fetcher;
public Counter(CountFetcher fetcher) {
this.fetcher = fetcher;
}
public getCounts() {
Promise<Integer> count1 = fetcher.getCount1();
Promise<Integer> count2 = fetcher.getCount2();
...
}
}
在您的生产代码中,您使用真实Counter
实例化CountFetcher
。在测试代码中,您注入了CountFetcher
的模拟版本,可以让每个单独的getCountXXX
方法返回您想要的任何内容:
public class MockCountFetcher extends CountFetcher {
@Override
getCount1() { return mockCount1; }
}
public class TestCounter {
@Test
public void smokeTest() {
CountFetcher mockFetcher = new MockCountFetcher();
Counter counter = new Counter(mockFetcher);
assertEquals(someExpectedValue, counter.getCounts());
}
}