Mocking both static and dynamic methods with PowerMock
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.
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;
}