Question

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.

Was it helpful?

Solution

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;
   }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top