Java 如何使用PowerMock模拟嵌套方法
假设我有两个类A和BJava 如何使用PowerMock模拟嵌套方法,java,unit-testing,junit4,powermock,easymock,Java,Unit Testing,Junit4,Powermock,Easymock,假设我有两个类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; } } 现在我想模拟methodA,它有一个对类B的嵌套方法调用。我已经尝试编写下面的测试用例,但是得到了methodNotImp
Class A{
public String methodA(String name) {
B b = new B();
b.methodB(name);
}
}
Class B{
public String methodB(String name) {
return name+name;
}
}
现在我想模拟methodA,它有一个对类B的嵌套方法调用。我已经尝试编写下面的测试用例,但是得到了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提前您可以通过执行以下操作来实现您的目标。注意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>
org.powermock
powermock api easymock
1.7.3
测试
这里有几个问题
首先,不要同时使用两个模拟框架。在一个框架中创建期望时,没有理由期望另一个框架知道它
第二,如前所述,如果您想模拟methodA
,假设这是使用a
的测试的一部分,那么没有理由模拟B
中的任何内容,因为methodA
的结果是模拟的,并且不会调用B
三,。也就是说,如果对象C
接受A
,它不应该得到具体的实现,而是应该得到它使用的接口。然后在测试中,模拟该接口,而不是类
考虑到这些,如果您为
A
创建一个接口,并从该接口截取响应,您的测试将更加简单,并且您不必求助于这些类型的工具。如果您想要模拟方法A
,则无需对类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
是解决方案。我通过添加Powermock.expectNew(B.class.).andreurn(B)解决了这个问题测试类中的code>和@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);
}
}
什么是嵌套方法?您正在使用power mock和easy mock??现在我想模拟methodA-如果methodA()被模拟,那么就没有必要模拟b.methodB()。使用多个测试框架是可以的,但easy mock很糟糕。我建议在您的项目中使用Powermock和mockito。使用powermock模拟新对象的创建以及模拟静态和最终方法。使用mockito进行其他操作。此外,我会使用eassy mock重新评估。只需在powermockito api中使用powermockito api即可尝试您的代码,但我得到了“NoClassDefFoundError”。您能给我堆栈跟踪吗?很抱歉,该代码是针对powermockito api的。您需要为powermock添加easymock api。我将更新答案EasyMock和PowerMock一起使用。这是使用它们的正常方式。没有什么不对的。事实上,你可以一起使用它们,并不意味着你应该一起使用。它们注定要一起使用。PowerMock不应该单独使用。但是,我建议永远不要使用PowerMock,除非在极端情况下。因为需要它意味着一个糟糕的设计。但是,当然,有时,你会被一个糟糕的设计所困扰。一个经过测试的糟糕设计比一个糟糕的设计要好