PowerMock: how to do EasyMock's expectPrivate() for Mockito? - java

PowerMock provides the method expectPrivate to mock out private methods, however it appears only in EasyMock api and not the Mockito API.
So, is there an equivalent for PowerMockito? I'm guessing not because I haven't found it and because of this wiki entry. but that doesn't actually prevent PowerMockito from working around it. So, I'm asking this mostly for confirmation and since I think this will be of value for others.

PowerMockito provides ways to mock private methods as well, from the API:
<T> WithOrWithoutExpectedArguments<T> when(Object instance, Method method)
Expect calls to private methods.
verifyPrivate(Object object, org.mockito.verification.VerificationMode verificationMode)
Verify a private method invocation with a given verification mode.
There are a bunch of other signatures of the type described above.
An example:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.mockito.Matchers.eq;
#RunWith(PowerMockRunner.class)
#PrepareForTest(Foo.class)
public class SimpleTest {
#Test
public void testHello() throws Exception {
Foo foo = PowerMockito.spy(new Foo());
foo.sayHello();
PowerMockito.verifyPrivate(foo).invoke("hello", eq("User"));
}
}
class Foo {
public void sayHello() {
System.out.println(hello("User"));
}
private String hello(String user) {
return "Hello " + user;
}
}

Related

mocking of instance void method is working without calling 'expectLastCall' method

I just written sample test case, where I would like to mock a void instance method. I am surprised, my test case is passing without calling the expectLastCall method. I would like to know, is calling of expectLastCall is not required while mocking instance void methods?
StringUtil.java
package com.sample.util;
import com.sample.model.MethodNotImplementedException;
public class StringUtil {
public String toUpperAndRepeatStringTwice(String str) {
String upperCase = str.toUpperCase();
sendStringToLogger(upperCase);
return upperCase + upperCase;
}
public void sendStringToLogger(String str){
throw new MethodNotImplementedException();
}
}
StringUtilTest.java
package com.sample.util;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ StringUtil.class })
public class StringUtilTest {
#Test
public void toUpperAndRepeatStringTwice() {
StringUtil stringUtil = PowerMock.createPartialMock(StringUtil.class, "sendStringToLogger");
String str = "HELLO PTR";
stringUtil.sendStringToLogger(str);
//PowerMock.expectLastCall().times(1);
PowerMock.replayAll();
String result = stringUtil.toUpperAndRepeatStringTwice("hello ptr");
assertEquals(result, "HELLO PTRHELLO PTR");
}
}
expectLastCall is not required. For EasyMock and the PowerMock layer as well. So you are right.
It is used for clarity for some users. Because it makes it obvious that the method before is an expectation not some random call. But it is more a question of style than a requirement.
You also don't need the time(1) since it is the default.
BTW, the answer here is wrong and I've commented on it accordingly.

Powermock/EasyMock: Set expectation on final method that would throw exception

How do I set an expectation on a final method if I can't safely invoke that method at all? PowerMock is supposed to ensure the invocation is mocked, but I can't even get to that stage:
WithFinal.java:
public class WithFinal {
public final void finalMethod() {
throw new RuntimeException();
}
}
CallsFinal.java:
public class CallsFinal {
private WithFinal withFinal;
public CallsFinal(WithFinal withFinal) {
this.withFinal = withFinal;
}
public void callFinal() {
withFinal.finalMethod();
}
}
PowerMockTest.java:
import org.easymock.EasyMock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.core.classloader.annotations.PrepareForTest;
import static org.powermock.api.easymock.PowerMock.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest(CallsFinal.class)
public class PowerMockTest {
#Test public void testFinal() {
WithFinal mock = createMock(WithFinal.class);
CallsFinal callsFinal = new CallsFinal(mock);
mock.finalMethod();
EasyMock.expectLastCall().atLeastOnce();
replay(mock);
callsFinal.callFinal();
verify(mock);
}
}
I get a RuntimeException on the very first call to mock.finalMethod(), which makes sense, but I thought the whole point of PowerMock was to make this possible?
There was a simple mistake in the test class: instead of #PrepareForTest(CallsFinal.class), it should have been #PrepareForTest(WithFinal.class).
PowerMock only requires that the calling class be prepared for test when mocking a system class from the JRE; otherwise, it's the class to be mocked itself that needs to get prepared.
Finally, I will mention there is another mocking library that can be used here, which I happen to develop: JMockit. With it, the test can be written as:
import org.junit.*;
import mockit.*;
public class JMockitTest {
#Tested CallsFinal callsFinal;
#Injectable WithFinal mock;
#Test public void testFinal() {
new Expectations() {{ mock.finalMethod(); }};
callsFinal.callFinal();
}
}
Using PowerMock, you can mock skip a internal method call instead of direct method call.
For example you want to test callFinal method of CallsFinal class which internally calling finalMethod of WithFinal class. So in this case if you don't want to instantiate WithFinal class then you need to mock WithFinal object to skip internal call for finalMethod.

PowerMock:: [java.lang.IllegalStateException: no last call on a mock available]

To mock a static method powermock giving an exception while expect().
#Test
public void testRegistrarService()
{
mockStatic(IdGenerator.class);
expect(IdGenerator.generateNewId()).andReturn(42L);
long actualId=serTestObj.registerService();
replay(IdGenerator.class);
verify(IdGenerator.class);
assertEquals(42L,actualId);
}
public class ServiceRegistrator
{
public long registerService()
{
long id = IdGenerator.generateNewId();
return id;
}
}
public class IdGenerator
{
public static long generateNewId()
{
return System.currentTimeMillis();
}
}
Exception is:
java.lang.IllegalStateException: no last call on a mock available
at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:521)
at org.easymock.EasyMock.expect(EasyMock.java:499)
at home.powermock.testServiceRegistrator.testRegistrarService(testServiceRegistrator.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:31)
how to mock staic method,while m using powerMock
i'm using intelliJ idea,how to resolve that exception.
Your code is missing the annotation
#PrepareForTest(IdGenerator.class)
In my case I was missing the following method in my test class
#ObjectFactory
/**
* Configure TestNG to use the PowerMock object factory.
*/
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
Once I added it, I got rid of the "no last call on a mock available" error.
You need to put the replay before the actual call to the method.
EDIT: I think part of the problem may be caused because of your imports. Try not to import static powermock and static easymock (I've found that I often confuse myself and forget which one I need to call replay on).
Try running the following code. If it doesn't run correctly, then it may be because of a problem with the particular version of PowerMock/EasyMock/Junit that you have.
TestClass:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest(IdGenerator.class)
public class TestClass {
#Test
public void testRegistrarService()
{
ServiceRegistrator serTestObj = new ServiceRegistrator();
PowerMock.mockStatic(IdGenerator.class);
expect(IdGenerator.generateNewId()).andReturn(42L);
PowerMock.replay(IdGenerator.class);
long actualId=serTestObj.registerService();
PowerMock.verify(IdGenerator.class);
assertEquals(42L,actualId);
}
}
IdGenerator:
public class IdGenerator {
public static long generateNewId()
{
return System.currentTimeMillis();
}
}
ServiceRegistrator:
public class ServiceRegistrator {
public long registerService()
{
long id = IdGenerator.generateNewId();
return id;
}
}
This question has been here for a long time but I'll try to give to it an aswer to explain what i did to resolve this problem.
First of all you have to use these two annotations:
#RunWith(PowerMockRunner.class)
This annotation let the current test class know what to use to run his tests, this is useful because we can use PowerMockRunner instead of JUnitRunner
#PrepareForTest(IdGenerator.class)
This annotation is used to prepare the class "IdGenerator" to be used in the test, prepare means that we will be able to mock the static methods as we do to the public methods
After added these two annotations we have to be sure we are using the right packages provided by PowerMock:
1) PowerMock:
Import: import org.powermock.api.easymock.PowerMock;
Use: We will use PowerMock to mock (and not only) our static method with the following code line
PowerMock.mockStatic(IdGenerator.class);
2) EasyMock:
Import: import org.easymock.EasyMock;
Use: We are going to use EasyMock to fake our object to be returned by our static method:
EasyMock.expect(IdGenerator.generateNewId()).andReturn(42L);
These was two examples on what are used PowerMock and EasyMock, and here I'll try to explain the code and what it does:
mockStatic(IdGenerator.class);
//We mock our IdGenerator class which have the static object
expect(IdGenerator.generateNewId()).andReturn(42L);
//We fake our method return object, when we'll call generateNewId()
//method it will return 42L
//With expecting we "record" our this method and we prepare it to be
//changed (it will return our decided value)
replay(IdGenerator.class);
//We go to perform our methods "registered" with the expect method
//inside the IdGenerator class, in this case with replay we just apply
//the changes of the expect to the method generateNewId()
long actualId = serTestObj.registerService();
//We create our object (which inside have a non static method that
//use generateNewId() static method)
verify(IdGenerator.class);
//We verify that the our faked method have been called
assertEquals(42L,actualId);
//We see if the two values are matching
Pay attention because replay must be used before you create the new object (actualId in this example) that will call the static faked methods.
Also do a lot of attention on what you are importing, for a distraction i was using
PowerMockito.mockStatic(className.class);
//from import org.powermock.api.mockito.PowerMockito;
Instead of
PowerMock.mockStatic(className.class);
//from import org.powermock.api.easymock.PowerMock;
I hope that this answer is clear and complete
By the way here i'll refer you to some useful links:
PowerMock Static Documentation on GitHub
Mvn Repository PowerMock Libraries
See you :D

PowerMock: Mocking static method that affect one test only

My situation:
I would like to add a new test. And I need to mock one static method X of Service class.
Unfortunately existing tests are using this static method in some way.
And when I mock X method using PowerMock then other test failed.
What is more I shouldn't touch other tests.
Is there any opportunity to mock static methods for one test only? ( using PowerMock).
Thanks in advance.
Sure, it is possible! The only time when you could run into problems is if you are trying to test multiple threads at the same time... I put an example of how to do it below. Enjoy.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest(IdGenerator.class)
public class TestClass {
#Test
public void yourTest()
{
ServiceRegistrator serTestObj = new ServiceRegistrator();
PowerMock.mockStatic(IdGenerator.class);
expect(IdGenerator.generateNewId()).andReturn(42L);
PowerMock.replay(IdGenerator.class);
long actualId = IdGenerator.generateNewId();
PowerMock.verify(IdGenerator.class);
assertEquals(42L,actualId);
}
#Test
public void unaffectedTest() {
long actualId = IdGenerator.generateNewId();
PowerMock.verify(IdGenerator.class);
assertEquals(3L,actualId);
}
}
TestClass
public class IdGenerator {
public static long generateNewId()
{
return 3L;
}
}
The easiest way to solve your problem is create new test class and place your tests there.
You can also wrap up this static class with normal class hidden behind interface in your code and stub this interface in your tests.
Last thing you can try is to stub each method of your static class in #SetUp method using:
Mockito.when(StaticClass.method(param)).thenCallRealMethod();
and stub particular method in your test using:
Mockito.when(Static.methodYouAreInterested(param)).thenReturn(value);
For those looking to achieve this using Mockito with PowerMocks, this can be done by adding the #PrepareForTest annotation to the tests themselves that need to mock out the values instead of the test class itself.
In this example, let's pretend there is SomeClass that has a static function (returnTrue()) that always returns true like so:
public class SomeClass {
public static boolean returnTrue() {
return true;
}
}
This example shows how we can mock out the static call in one test and allow the original functionality to stay the same in another.
#RunWith(PowerMockRunner.class)
#Config(constants = BuildConfig.class)
#PowerMockIgnore({"org.mockito.*", "android.*"})
public class SomeTest {
/** Tests that the value is not mocked out or changed at all. */
#Test
public void testOriginalFunctionalityStays()
assertTrue(SomeClass.returnTrue());
}
/** Tests that mocking out the value works here, and only here. */
#PrepareForTest(SomeClass.class)
#Test
public void testMockedValueWorks() {
PowerMockito.mockStatic(SomeClass.class);
Mockito.when(SomeClass.returnTrue()).thenReturn(false);
assertFalse(SomeClass.returnTrue())
}
}

Mock Runtime.getRuntime()?

Can anyone make any suggestions about how best to use EasyMock to expect a call to Runtime.getRuntime().exec(xxx)?
I could move the call into a method in another class that implements an interface, but would rather not in an ideal world.
interface RuntimeWrapper {
ProcessWrapper execute(String command) throws IOException;
}
interface ProcessWrapper {
int waitFor() throws InterruptedException;
}
I was wondering if anyone had any other suggestions?
Your class shouldn't call Runtime.getRuntime(). it should expect a Runtime to be set as its dependency, and work with it. Then in your test you can easily provide a mock and set it as a dependency.
As a sidenote, I'd suggest watching this lecture on OO Design for testability.
Update: I didn't see the private constructor. You can try using java bytecode instrumentation in order to add another constructor or make the constructor public, but that might turn out to be impossible as well (if there are some restrictions on that class).
So your option is to make a wrapper (as you suggested in the question), and follow the dependency-injection approach.
Bozho above is IMO the Correct Solution. But it is not the only solution. You could use PowerMock or JMockIt.
Using PowerMock:
package playtest;
public class UsesRuntime {
public void run() throws Exception {
Runtime rt = Runtime.getRuntime();
rt.exec("notepad");
}
}
package playtest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.legacy.PowerMockRunner;
import static org.powermock.api.easymock.PowerMock.*;
import static org.easymock.EasyMock.expect;
#RunWith(PowerMockRunner.class)
#PrepareForTest( { UsesRuntime.class })
public class TestUsesRuntime {
#Test
public void test() throws Exception {
mockStatic(Runtime.class);
Runtime mockedRuntime = createMock(Runtime.class);
expect(Runtime.getRuntime()).andReturn(mockedRuntime);
expect(mockedRuntime.exec("notepad")).andReturn(null);
replay(Runtime.class, mockedRuntime);
UsesRuntime sut = new UsesRuntime();
sut.run();
}
}
Perhaps instead of mocking Runtime.getRuntime().exec() you could "mock" the script/program/etc. it's supposed to be calling.
Instead of passing the real command-line string into exec(), write a test script and execute it instead. You could have the script return hard-coded values you could test against just like a mocked class.
Here is how you would do it with EasyMock 3.0 (and JUnit 4):
import org.junit.*;
import org.easymock.*;
import static org.easymock.EasyMock.*;
public final class EasyMockTest extends EasyMockSupport
{
#Test
public void mockRuntimeExec() throws Exception
{
Runtime r = createNiceMock(Runtime.class);
expect(r.exec("command")).andReturn(null);
replayAll();
// In tested code:
r.exec("command");
verifyAll();
}
}
The only problem with the test above is that the Runtime object needs to be passed to code under test, which prevents it from using Runtime.getRuntime().
With JMockit, on the other hand, the following test can be written, avoiding that problem:
import org.junit.*;
import mockit.*;
public final class JMockitTest
{
#Test
public void mockRuntimeExec() throws Exception
{
final Runtime r = Runtime.getRuntime();
new NonStrictExpectations(r) {{ r.exec("command"); times = 1; }};
// In tested code:
Runtime.getRuntime().exec("command");
}
}

Categories

Resources