Java 如何使用PowerMock模拟嵌套方法

Java 如何使用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

假设我有两个类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的嵌套方法调用。我已经尝试编写下面的测试用例,但是得到了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)解决了这个问题
@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,除非在极端情况下。因为需要它意味着一个糟糕的设计。但是,当然,有时,你会被一个糟糕的设计所困扰。一个经过测试的糟糕设计比一个糟糕的设计要好