我想澄清TDD范围内的重构。
在:
class Somclass{
public void sendMessage(){
WebServiceStub stub = new WebServiceStub();
...
stub.sendMsg();
}
}
后:
class Somclass{
private WebServiceStub stub;
public void sendMessage(){
...
if(stub == null){
stub = new WebServiceStub();
}
...
stub.sendMsg();
}
}
所以我想验证sendMsg()方法并使用result生成一些断言。为了具有模拟此存根的可能性,我将此存根局部变量移动到实例变量。这样我就可以将mock存根设置为类,并在测试类中进行verivyings和asserts。例如:
@Test
public void testSMth(){
wsProvider.setStub(stubMock);
verify(stubMock).sendMsg();
...asserts
}
这种方法不是线程安全的,我应该做一些并发修改。这种修改可能会导致错误。所以在局部变量approce中有线程安全。
此外,我可以创建将返回WebServiceStub实例的Factory。但是这种方法会产生新的课程,因为这种情况经常发生。
有一个问题:如何测试这种情况并进行粗略测试可能导致错误的成本修改?
答案 0 :(得分:4)
您的班级应该将WebService
对象(我拒绝将其称为“存根”)作为字段。
class Someclass{
@Resource
private WebService ws;
public void sendMessage(){
ws.sendMsg();
}
}
应该注入您选择的DI框架。在测试中,您可以将其设置为模拟。没有必要使用懒惰的getter,因为你的观点是不是线程安全的。
答案 1 :(得分:3)
使用constructor injection以避免未设置依赖项的可能性。这将允许您在测试中轻松使用模拟。
如果WebServiceStub
类实际上不是线程安全的(但如果JAX-WS生成WebServiceStub
,那么你应该知道metro / jax-ws存根通常是线程安全的),那么是的,你将不得不使用工厂。这并不是什么大不了的事,它不应该让你失望那么多。如果需要,可以使用静态内部类。
答案 2 :(得分:0)
它看起来几乎是正确的,但如果stub == Null则永远不会实例化stub。相反,thow ArgumentNullException。 Null永远不应该被接受作为一个有效的论据(除非你有一个非常,非常,非常好的理由)。