这是一个场景,我在一个类 MyClass
的方法中有类似的东西public class MyClass{
public Object build(Map map) {
BaseClass cls;
if(SomeconditionTrue) {
cls = new ChildClass1(new ABC());
} else {
cls = new ChildClass2(new ABC());
}
cls.callMethod();
}
}
对于上面的场景,我正在使用PowerMockito编写测试用例,我想模拟这个方法调用cls.callMethod()
。当我试图模拟时,它调用失败的实际方法callMethod()
。有人可以帮我模仿那个方法吗?尝试使用PowerMockito PowerMockito.stub和一些其他选项使用几个场景,但它总是调用实际方法。模拟这个方法的原因是,它有一个不同的逻辑,它调用不同的API,方法相当复杂,因此我们需要模拟这个方法。
答案 0 :(得分:1)
你可以转向Powermock,但这并不一定是解决此类问题的“最佳”答案。
从本质上讲,您在代码中调用 new 的事实让您感到悲伤 - 您创建了难以测试的代码。你可能会看到这些videos来理解我在说什么。
长话短说:而不是转向大型Powermock锤子,你可以改为修改你的代码;使用依赖注入。因此,不是自己创建这些对象,而是测试中的类可以使用一些工厂对象来提供它所需的对象。然后你可以使用任何“普通”的模拟框架,如EasyMock或Mockito来创建该工厂的模拟版本。
编辑:我认为你可能过度复杂了整个问题。你知道,有一个基类或两个子类并不重要。事情是:对于每种测试方法,您应该准确地了解将采用哪种路径。你要么想要创建一个child1,要么是一个孩子。因此,我为您创建了一个简化的解决方案:
package ghostcat.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
class Abc {}
abstract class Base {
void callMethod() {
System.out.println("Base::callMethod");
}
}
class ChildClass1 extends Base {
ChildClass1(Abc abc) {}
}
class MyClass {
public Object build() {
System.out.println("build1");
Base cls = new ChildClass1(new Abc());
System.out.println("build2");
cls.callMethod();
System.out.println("build3");
return null;
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(MyClass.class)
public class MockNewTest {
@Test
public void test() throws Exception {
ChildClass1 mock = Mockito.mock(ChildClass1.class);
PowerMockito.whenNew(ChildClass1.class).withArguments(Mockito.any(Abc.class)).thenReturn(mock);
new MyClass().build();
}
}
打印:
build1
build2
build3
所以你可以看到 - 基地里没有任何东西被召唤;只是因为那个子对象被“完全”嘲笑了。
重点是:您的测试代码只需要某种类型的一个对象;而且你事先知道那是child1还是child2。所以你只需为该类创建一个 mock ;并使用PowerMockito返回你刚刚创建的模拟。
记录:我和间谍玩了一段时间;但他们在这里没有帮助;它们也不是必需的!