使用PowerMock模拟静态和动态方法

时间:2011-02-02 13:28:31

标签: java mocking easymock powermock

假设我们有

public class Foo {
   public static Foo getInstance() {...}

   public Bar bar(Baz baz) {...}
}

我想要做的是在单元测试中模拟它。我需要模拟类Foo的静态和动态方法。模拟getInstance()就像

一样简单
import static org.powermock.api.easymock.PowerMock.replace;
import static org.powermock.api.easymock.PowerMock.method;

public class MyTest {

   @Test
   public void myTest() {
      replace(method(Foo.class, "getInstance"))
         .with(method(MyTest.class, "getMockInstance"));
   }

   public static Foo getMockInstance() {
      Foo foo = EasyMock.createMock(Foo.class);
      EasyMock.replay(foo);
      return foo;
   }
}

问题是,如何模拟bar方法?

replace(method(...)).with(method(...))的上一个技巧不起作用,因为它不适用于动态方法。

尝试在已经模拟的类之上进行模拟也不起作用:

...
@Test
public void myTest() {
      replace(method(Foo.class, "getInstance"))
         .with(method(MyTest.class, "getMockInstance"));

      Foo foo = Foo.getInstance();  // works well
      Baz baz1 = new Baz();
      Baz baz2 = new Baz();
      EasyMock.expect(foo.bar(baz1)).andReturn(baz2);  // exception thrown
      EasyMock.replay(foo);
}
...

上面的代码会引发AssertionError: Unexpected method call bar

那么我该如何做到呢?我不想将.bar(...)模仿到getMockInstance,因为在现实世界中,我需要一些静态getMockInstance方法无法获得的数据。

1 个答案:

答案 0 :(得分:3)

我认为问题在于,您在foo模拟两次调用重播,一次在模拟静态方法getMockInstance()中,一次在您告诉模拟foo期望foo.bar(bar1)之后1}}打电话。尝试将getMockInstance()更改为

   public static Foo getMockInstance() {
      Foo foo = EasyMock.createMock(Foo.class);
      return foo;
   }

然后告诉EasyMock在您告诉它期待foo方法调用后重播bar。所以MyTest.java看起来像这样:

@Test
public void myTest() {
      replace(method(Foo.class, "getInstance"))
         .with(method(MyTest.class, "getMockInstance"));

      Foo foo = Foo.getInstance();  // works well
      Baz baz1 = new Baz();
      Baz baz2 = new Baz();
      EasyMock.expect(foo.bar(baz1)).andReturn(baz2);  // exception thrown
      EasyMock.replay(foo);
}

  public static Foo getMockInstance() {
      Foo foo = EasyMock.createMock(Foo.class);
      return foo;
   }