PowerMock: Mocking static method that affect one test only - java

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())
}
}

Related

Powermock static final method in final class

The Test case I am writing for:
public class AClassUnderTest {
// This test class has a method call
public Long methodUnderTest() {
// Uses the FinalUtilityClass which contains static final method
FinalUtilityClass.myStaticFinalMethod(<3-parameters-here>);
// I want to mock above call so that test case for my "methodUnderTest" passes
}
}
I have one final class.
public final class FinalUtilityClass {
/**
* Method has 3 parameters
*/
public static final MyBean myStaticFinalMethod(<3-parameters-here>) {
}
}
I have already added below code in my test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ FinalUtilityClass.class })
I want to write test case for mocking it.
I want to mock the call of myStaticFinalMethod() so that I can get the expected MyBean instatnce which I can use in further code to pass my test case.
The <3-parameters-here> are Calendar, String, String.
I tried doing:
1)
PowerMockito.mock(FinalUtilityClass.class)
PowerMockito.when(FinalUtilityClass.myStaticFinalMethod(<3-parameters-here>).thenReturn(new MyBean());
2)
PowerMockito.mockStatic(FinalUtilityClass.class)
PowerMockito.when(FinalUtilityClass.myStaticFinalMethod(<3-parameters-here>).thenReturn(new MyBean());
3)
PowerMockito.spy(FinalUtilityClass.class)
PowerMockito.when(FinalUtilityClass.myStaticFinalMethod(<3-parameters-here>).thenReturn(new MyBean());
But nothing worked for me. Please suggest what is correct way for mocking static final method in final class.
The following steps are required to mock calls to static methods:
Use the #RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
Use the #PrepareForTest(ClassThatContainsStaticMethod.class) annotation at the class-level of the test case
Use PowerMock.mockStatic(ClassThatContainsStaticMethod.class) to mock all methods of this class
When you follow these steps as documented, your tests should work. And as the OP seems to be confused about PowerMock vs. PowerMockito - that is (more or less) the same thing:
PowerMock and PowerMockito are based on the same technology. They just have different "connectors" to either work with EasyMock or Mockito. So, yes the above example says PowerMock.mockStatic() - but PowerMockito has mockStatic() methods as well. In that sense: the core things (for example regarding preparation with annotations) are the same. See here for example (they are so close that the linked tutorial says "Intro to PowerMock" - although it does introduce PowerMockito.
And as you seem to not believe me - see this example:
package ghostcat.test;
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;
final class ClassWithStatic {
public final static int ignoreMethodCall(String a, String b, int c) {
System.out.println("SHOULD NOT SHOW UP: " + a);
return c;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassWithStatic.class)
public class MockStaticTest {
#Test
public void test() {
PowerMockito.mockStatic(ClassWithStatic.class);
PowerMockito.when(ClassWithStatic.ignoreMethodCall("a", "b", 5)).thenReturn(42);
org.junit.Assert.assertEquals(ClassWithStatic.ignoreMethodCall("a", "b", 5), 42);
}
}
This test passes; and doesn't print anything. Therefore the final static method gets mocked.
I faced a similar problem, and it cost me a lot of time.
I solved it, based on this Mock system class with PowerMock documentation, when I realized that the #PrepareForTest({ SomeClassToBePreparedForTesting.class }) must receive the class that calls the static methods defined in the final class, so the preparation for the test, in your case, must receive the AClassUnderTest.class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ AClassUnderTest.class })
The correct way to mock the final class with the target static method is to use the PowerMock.mockStatic(FinalClassThatDefinesStaticMethod.class), in your case the FinalUtilityClass.class.
PowerMockito.mockStatic(FinalUtilityClass.class)
PowerMockito.when(FinalUtilityClass.method(params)).thenReturn(return);
In addition, if you have some issue like: 'It's not possible to mock final methods', you can create the file org/powermock/extensions/configuration.properties and set this config mockito.mock-maker-class=mock-maker-inline like the PowerMockito documentation presents.

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.

Recursively call system while mocking

I've been trying for a while to mock my codes. I'm newby on mocking so lots of things ahead of me to catch. I'm using Powermockito with Mockito and Easymock integration.
I'm having difficulties with mocking a method which is inside the method I wanted to test. So here is an example of the situation I faced:
public class trialClass {
public static int try2(){
return 3;
}
public static int try(int a){
return try2() + a;
}
}
and my test class is:
#RunWith(PowerMockRunner.class)
#PrepareForTest(trial.class)
public class trialTest {
#Before
public void setUp() throws Exception {
PowerMockito.mockStatic(trial.class);
//Here I expect try2() to return 10, even it return 3
PowerMockito.when(trial.try2()).thenReturn(10);
}
#Test
public void testtry() throws Exception {
//After try2() returns 10 recursively inside my try() method,
//I expect result to be 11
Assert.assertEquals(11, trial.try(1));
}
}
This question of mine actually comes from my session variable. My session holds some value and an X method returns that value. All I need is to mock that X method recursively and this question just simulates this case.
Thanks for your help guys.
You need to use Mockito.CALLS_REAL_METHODS
So in your test setup:
PowerMockito.mockStatic(trial.class, CALLS_REAL_METHODS);
EDIT
It occurred to me that you might not want to change to EasyMock instead of Mockito, in that case please disregard...
Partial mocking is the keyword you are after. You don't want to mock everything, just try2(). You should use the PowerMock.mockStaticPartial(Class, String...) method.
Instead of
PowerMockito.mockStatic(trialClass.class);
Use
PowerMock.mockStaticPartial(trialClass.class, "try2");
And then do the actual mocking.
Also note that you defined the clas as trialClass in the code above, but use trial.class in the second code...
Please find an updated version of your TrialTest.java using EasyMock with PowerMock as a solution. PowerMock is easy to configure and does not interfere with most existing jars. You only need a few JARS
powermock-easymock-X.X.X-full.jar
Easymock-X.X.jar
You had some issues with your code that I fixed:
Code Issue: try is a Java keyword so it cannot be used in method name (e.g., try(int a)).
Code Quality: Use Java Object instead of Java primitive (e.g., Use Integer instead of int).
Code Quality: trialClass is a poor Java class name (e.g., Use upperCase for Java class name, don't use the generic word Class unless for educational purposes), maybe Trial.
Here's the updated code:
Trial.java (CUT)
public class Trial {
public static Integer try2() {
return 3;
}
public static Integer try1(int a) {
return try2() + a;
}
}
Working Test Class: TrialTest.java
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Before;
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(Trial.class)
public class TrialTest {
#Before
public void setUp() throws Exception {
/* Setup */
PowerMock.mockStaticPartial(Trial.class, "try2");
/* Mocks */
// Here I expect try2() to return 10, even it return 3
EasyMock.expect(Trial.try2()).andReturn(10).atLeastOnce();
PowerMock.replayAll();
}
#Test
public void testtry() throws Exception {
// After try2() returns 10 recursively inside my try() method,
// I expect result to be 11
/* Test */
Integer result = Trial.try1(1);
/* Asserts */
PowerMock.verifyAll();
Assert.assertEquals(new Integer(11), result);
}
}

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

How to mock static method in Java?

I have a class FileGenerator, and I'm writing a test for the generateFile() method that should do the following:
1) it should call the static method getBlockImpl(FileTypeEnum) on BlockAbstractFactory
2) it should populate variable blockList from the subclass method getBlocks()
3) it should call a static method createFile from a final helper class FileHelper passing a String parameter
4) it should call the run method of each BlockController in the blockList
So far, I have this empty method:
public class FileGenerator {
// private fields with Getters and Setters
public void generateBlocks() {
}
}
I am using JUnit, Mockito to mock objects and I've tried using PowerMockito to mock static and final classes (which Mockito doesn't do).
My problem is: my first test (calling method getBlockList() from BlockAbstractFactory) is passing, even though there is no implementation in generateBlocks(). I have implemented the static method in BlockAbstractFactory (returning null, so far), to avoid Eclipse syntax errors.
How can I test if the static method is called within fileGerator.generateBlocks()?
Here's my Test Class, so far:
#RunWith(PowerMockRunner.class)
public class testFileGenerator {
FileGenerator fileGenerator = new FileGenerator();
#Test
public void shouldCallGetBlockList() {
fileGenerator.setFileType(FileTypeEnum.SPED_FISCAL);
fileGenerator.generateBlocks();
PowerMockito.mockStatic(BlockAbstractFactory.class);
PowerMockito.verifyStatic();
BlockAbstractFactory.getBlockImpl(fileGenerator.getFileType());
}
}
I have no experience with PowerMock, but since you didn't get an answer yet I'm just been reading through the documentation to see if I can help you a bit on your way.
I found that you need to prepare PowerMock so that I knows which static methods it needs to prepare to be mocked. Like so:
#RunWith(PowerMockRunner.class)
#PrepareForTest(BlockAbstractFactory.class) // <<=== Like that
public class testFileGenerator {
// rest of you class
}
Here you can find more information.
Does that help?
Working example:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClassStaticA.class, ClassStaticB.class})
public class ClassStaticMethodsTest {
#Test
public void testMockStaticMethod() {
PowerMock.mockStatic(ClassStaticA.class);
EasyMock.expect(ClassStaticA.getMessageStaticMethod()).andReturn("mocked message");
PowerMock.replay(ClassStaticA.class);
assertEquals("mocked message", ClassStaticA.getMessageStaticMethod());
}

Categories

Resources