假设我有两个A和B类。
Class A{
public String methodA(String name) {
B b = new B();
b.methodB(name);
}
}
Class B{
public String methodB(String name) {
return name+name;
}
}
现在我想模拟方法A,它有一个嵌套方法调用类B.我尝试编写下面的TestCase,但得到 methodNotImplementedException 。
@Test
public void testCase() {
A a = new A();
B b = PowerMock.createPartialMock(B.class, "methodB");
EasyMock.expect(b.methodB(anyString())).andReturn("HELLO PTR");
PowerMock.replayAll();
String result = a.methodA("hello ptr");
assertEquals(result, "HELLO PTRHELLO PTR");
PowerMock.verifyAll();
}
任何人都可以告诉如何使用PowerMock解决嵌套方法调用.. ?? Thanx提前
答案 0 :(得分:2)
这里有几个问题。
首先,不要同时使用两个模拟框架。没有理由期望在一个框架中创建期望,另一个框架会知道它。
其次,如果如上所述,您想要模拟methodA
,据说是对使用A
的某些内容进行测试的一部分,则没有理由从B
模拟任何内容,因为methodA
的结果被模拟,并且不会调用B
。
第三,mock roles, not objects。这意味着,如果对象C
接受A
,它不应该得到具体的实现,而应该得到它使用的接口。然后在测试中,您模拟该接口,而不是类。
鉴于这些,如果您为A
创建一个接口,并从该接口存根响应,那么您的测试将更加简单,您将不必使用这些工具。
答案 1 :(得分:0)
您可以通过执行以下操作来实现目标。注意whenNew调用
@Test
public void testCase() {
A a = new A();
B b = PowerMock.createPartialMock(B.class, "methodB");
EasyMock.expect(b.methodB(anyString())).andReturn("HELLO PTR");
PowerMock.expectNew(B.class).andReturn(b);
PowerMock.replay(B.class);
String result = a.methodA("hello ptr");
assertEquals(result, "HELLO PTRHELLO PTR");
PowerMock.verifyAll();
}
您还需要将@PrepareForTest(B.class)
添加到测试类
最后,您需要添加api依赖
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-easymock</artifactId>
<version>1.7.3</version>
<scope>test</scope>
</dependency>
答案 2 :(得分:0)
如果你想模仿methodA
那么就没有必要对B课做任何事情。只是做
@Test
public void testCase() {
A a = mock(A.class);
expect(a.methodA()).andReturn("HELLO");
replay(a);
// use the mock to test something
String result = a.methodA("hello ptr");
assertEquals(result, "HELLO");
verify(a);
}
但看起来你想要测试A和模拟B.这是不同的。首先,我建议重构。即使是非常基本的,如
public class A{
public String methodA(String name) {
B b = newB();
b.methodB(name);
}
protected B newB() {
return new B()
}
}
这样,你根本不需要PowerMock。你可以做到
@Test
public void testCase() {
A a = partialMockBuilder().addMockedMethod("newB").mock(A.class);
B b = mock(B.class);
expect(a.newB()).andReturn(b);
expect(b.methodB()).andReturn("HELLO");
replay(a, b);
String result = a.methodA("HI");
assertEquals(result, "HELLO");
verify(a, b);
}
然后,如果你真的需要一些奇怪的理由来模仿new B()
,是的,使用Powermock.expectNew
是解决方案。
答案 3 :(得分:0)
我通过在测试类中添加PowerMock.expectNew(B.class).andReturn(b);
和@Mock
注释来解决此问题。
完整代码;
public class A {
public String methodA(String name) {
B b = new B();
return b.methodB(name);
}
}
public class B{
public String methodB(String name) {
return name+name;
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest({ A.class, B.class })
public class TestCase {
@Mock
private B b;
@Test
public void testCase() throws Exception {
A a = new A();
PowerMock.expectNew(B.class).andReturn(b);
EasyMock.expect(b.methodB(anyString())).andReturn("HELLO");
PowerMock.replay(B.class, b);
String result = a.methodA("HI");
assertTrue(result != null);
assertEquals(result, "HELLO");
PowerMock.verify(B.class, b);
}
}