如何使用PowerMock模拟嵌套方法

问题描述 投票:0回答:4

假设我有两个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;
   }
}

现在我想要模拟方法,它有一个嵌套方法调用类B.我尝试编写下面的TestCase但获取方法NotImplementedException。

@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提前

java unit-testing junit4 powermock easymock
4个回答
2
投票

这里有几个问题。

首先,不要同时使用两个模拟框架。在一个框架中创建期望时,没有理由期望另一个框架能够了解它。

其次,如果,如上所述,你想模仿methodA,据说是对使用A的东西的测试的一部分,那么没有理由从B模拟任何东西,因为methodA的结果被嘲笑,并且不会调用B

第三,mock roles, not objects。意思是,如果对象C接受A,它不应该得到具体的实现,而应该得到它使用的接口。然后在测试中,您模拟该接口,而不是类。

鉴于这些,如果您为A创建一个接口,并从该接口存根响应,您的测试将更加简单,您将不必诉诸这些类型的工具。


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>

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就是解决方案。


0
投票

我通过在Test Class中添加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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.