Prevent calling constructor - Mockito
假设我有classA和classB:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class A {
private B b ;
public A (String id ){
this. b = new B (id );
}
public void doSomethingA (String id ){
// do somethingA
}
}
public class B {
public B (String id ){
// call anotherThing (id)
}
public void doSomethingB (){
//somethingB
}
} |
现在我想测试classA里面的方法(用它的实例)但是想要模拟classB
Mockito允许我模拟classB,但是当我实例化classA时,构造函数调用classB(我想避免)
有没有办法只模拟构造函数(classA或classB)而不是其他方法?
-
您可以使用PowerMockito来模拟new B(id)调用。请参阅:benkiefer.com/blog/2013/04/23/powermockito-constructor-mocking
-
@tsolakp我们想要隔离的依赖关系必须成为类API的一部分。将它们隐藏在实施中是矛盾的。
-
@davidxxx。按照你的逻辑,我们永远不应该直接创建依赖关系,只应该使用工厂或DI。我发现它太极端,基于意见而且不同意你需要避免使用静态方法调用,new构造(例如用new Date)只是为了不使用像PowerMock这样的库。
-
@tsolakp我没有说永远不会。我说"我们想要孤立的依赖"。因为我们不想隔离它们,因为我们认为它们是内部的一部分,所以使依赖关系可见是一个错误,在这种情况下我们也不想模仿它们。
-
@davidxxx。这就是我的观点。我们仍然可以直接在类中创建依赖项并模拟它们。如果将它们暴露出来是另一个问题。至于模拟私有方法或依赖项,它取决于。这有两个方面。一方面说我们应该只做"灰色"盒子单元测试而不用担心测试/模拟私有方法/依赖项。另一方面说要进行全白盒测试,包括测试/模拟私有方法。我更倾向于中间。如果它只有业务逻辑,则测试私有方法(如果使用则模拟私有依赖项)。
-
@tsolakp在这种情况下,我也会测试但不是真的这样。但正如你所说,这是一个观点。我理解你的,但我完全不同意。谢谢你的分享。您可以阅读这个问题:stackoverflow.com/questions/7075938/这很有趣。我写了一个迟到的答案。它解释了我对测试私有方法的看法。
-
@davidxxx。谢谢你的链接。
你可以模拟任何B对象,但你不想这样做。
您想要模拟A类的B b字段。
哪个是不同的。
您必须重构您的设计并执行B实例化依赖而不是内部处理。
一种简单的方法是直接传递B变量而不是String作为参数:
1 2 3 4 5 6 7 8 9 10 11 12
| public class A {
private B b ;
public A (B b ){
this. b = b ;
}
public void doSomethingA (String id ){
// do somethingA
}
} |
现在嘲笑是直的:
1 2 3 4 5
| @Mock B b;
public void test(){
A a = new A(b);
} |
另一种方法是使用Function。
1 2 3 4 5 6 7 8 9 10 11 12
| public class A {
private B b ;
public A (Function <String, B > bFunction, String id ){
this. b = bFunction. apply(id );
}
public void doSomethingA (String id ){
// do somethingA
}
} |
模拟变得如此:
1 2 3 4 5
| @Mock B b;
public void test(){
A a = new A(s-> b,"anyValue");
} |
实现代码可以将A实例化为:
1
| A a = new A(B::new,"id"); |