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

发布于 2024-10-15 08:13:08 字数 1409 浏览 2 评论 0原文

假设我们有

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:意外的方法调用栏

那么我该如何做到这两点呢?我不想将 .bar(...) 的模拟放入 getMockInstance 中,因为在现实世界中,我需要一些静态<代码>中无法获得的数据。代码>getMockInstance方法。

Let's say we have

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

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

What I want to do is to mock it in my unit tests. I need to mock both static and dynamic methods of a class Foo. Mocking getInstance() is as easy as

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;
   }
}

The question is, how to mock bar method?

Previous trick with replace(method(...)).with(method(...)) does not work as it is not designed for dynamic methods.

Trying to mock on top of already mocked class also doesn't work:

...
@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);
}
...

Code above throws AssertionError: Unexpected method call bar.

So how do I do both? I don't want to put mocking of .bar(...) into the getMockInstance because in the real world I need some data that is not available from within static getMockInstance method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

傾旎 2024-10-22 08:13:08

我认为问题在于您在 foo 模拟上调用重播两次,一次在模拟静态方法 getMockInstance() 中,一次在您告诉模拟 foo< /code> 期待 foo.bar(bar1) 调用。尝试将 getMockInstance() 更改为

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

,然后告诉 EasyMock 在等待 bar 方法调用后重播 foo 。所以 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;
   }

I think the issue is that you are calling replay on your foo mock twice, once in the mocked static method getMockInstance() and once after you tell mocked foo to expect the foo.bar(bar1) call. Try altering the getMockInstance() to

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

and then telling EasyMock to replay foo after you tell it to expect the bar method call. So the MyTest.java would look something like this:

@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;
   }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文