在这种情况下?
class A {
public void f() {
B b = new B();
C c = new C();
// use b and c, and how to modify their behaviour?
}
}
我如何用PowerMock
和EasyMock
来实现我的想法?
我不想因为测试的原因而改变我的紧凑代码
实际上,您可以使用PowerMock模拟对象构造。这里有很棒的文档:https://code.google.com/p/powermock/wiki/MockConstructor
还看一下这个示例,它遍历了mock对象的构造。
您可以这样做,参见Matt Lachman的答案。不过,我们并不推荐这种方法。这有点俗气。
最好的方法是将依赖对象的创建委托给工厂模式,并将工厂注入A
类:
class BFactory {
public B newInstance() {
return new B();
}
}
class CFactory {
public C newInstance() {
return new C();
}
}
class A {
private final BFactory bFactory;
private final CFactory cFactory;
public A(final BFactory bFactory, final CFactory cFactory) {
this.bFactory = bFactory;
this.cFactory = cFactory;
}
public void f() {
B b = bFactory.newInstance();
C c = cFactory.newInstance();
}
}
然后模拟工厂以返回依赖类的模拟实例。
如果由于某种原因这是不可行的,那么你可以在A
类中创建工厂方法
class A {
public void f() {
B b = newB();
C c = newC();
}
protected B newB() {
return new B();
}
protected C newC() {
return newC();
}
}
然后你可以使用一个spy
来模拟那些工厂方法。
如果不更改代码,它将无法工作。(可测试性设计)。您可以用工厂方法替换B,它在实际中创建B1,或在测试中创建BTest,两者都实现了IB接口。
看起来你需要依赖注入。
您正在创建 B和C的具体实例,那么您不能修改行为
将实例作为参数传递给f(InterfaceB b, InterfaceC c)
,您应该使用多态性,然后您可以将需要更改其行为的模拟实例作为参数传递给该方法。所以方法不需要关心传递给它的具体实例的类型,你可以实现你需要的。
我知道接口的名字是不合逻辑的,但这可以很容易地解释上下文