I am using Powermock + Mockito2 + JUnit4 to unit test a class.
When I try to run ApiCreatorFacadeImplTest.java, it does not work and throw java.lang.ExceptionInInitializerError. I don't know how to fix it. Can anyone please point out what mistake am I making?
import static org.powermock.api.mockito.PowerMockito.mock;
#RunWith(PowerMockRunner.class)
#PrepareForTest({HttpUtil.class})
public class ApiCreatorFacadeImplTest {
private ServiceVersionFacade serviceVersionFacade;
private ServiceFacade serviceFacade;
private ApiCreatorFacadeImpl apiCreatorService;
#Before
public void setUp() {
apiCreatorService = new ApiCreatorFacadeImpl();
// mock ApiCreatorFacadeImpl fields
serviceVersionFacade = mock(ServiceVersionFacade.class);
serviceFacade = mock(ServiceFacade.class);
// inject fields to apiCreatorService
Whitebox.setInternalState(apiCreatorService, "serviceVersionFacade", serviceVersionFacade);
Whitebox.setInternalState(apiCreatorService, "serviceFacade", serviceFacade);
}
#Test
public void createHsfTypeApi() {
// do nothing
}
#Test
public void getApiTestParam() {
// do nothing
}
}
detail exception:
java.lang.ExceptionInInitializerError
at org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter.<init>(ConditionalStackTraceFilter.java:17)
at org.mockito.exceptions.base.MockitoException.filterStackTrace(MockitoException.java:41)
at org.mockito.exceptions.base.MockitoException.<init>(MockitoException.java:30)
at org.mockito.exceptions.misusing.MockitoConfigurationException.<init>(MockitoConfigurationException.java:18)
at org.mockito.internal.configuration.plugins.PluginLoader.loadImpl(PluginLoader.java:66)
at org.powermock.tests.utils.impl.PowerMockTestNotifierImpl.notifyBeforeTestMethod(PowerMockTestNotifierImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:308)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:131)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.access$100(PowerMockJUnit47RunnerDelegateImpl.java:59)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$TestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:147)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.NullPointerException
at org.mockito.internal.configuration.plugins.Plugins.getStackTraceCleanerProvider(Plugins.java:17)
at org.mockito.internal.exceptions.stacktrace.StackTraceFilter.<clinit>(StackTraceFilter.java:21)
... 38 more
Possible reason is that Powermockito, Mockito's version conflict. Could you examine Powermockito, mockito's supported version. You can look
this page.
I had the same problem. This is due to incompatible versions of the Mockito library. You should use powermock-api-mockito in a case if you are already using Mockito 1.x and use powermock-api-mockito2 when using Mockito 2.x.
P.S. For example, if you are using Spring Boot and spring-boot-starter-test dependency then your project already includes the Mockito dependency, check the Spring Boot Parent's BOM-file (pom-file with versions of dependencies) for the version of the Mockito.
Related
I am trying to upgrade from Mockito version 1.0.19 to 4.0.0 and using Junit 5, since I am unable to mock static in older version of mockito. I am getting "Failed to Release mocks" error..
Please let me know , what all needs to be taken care while migrating.
public class RefreshTableSchedulerTest {
#Mock
ConfigRepository configRepository;
#InjectMocks
RandomScheduler randomScheduler;
#BeforeEach
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
setReflectionUtils(randomScheduler);
}
#Test
public void testRefreshTableWithOutDelay() {
// our trestcases
}
RandomScheduler
#Configuration
#EnableScheduling
public class RandomScheduler {
#Scheduled(fixedDelayString = "${schedule.refresh.table.job.in.ms:1800000}")
public void execute() {
//fetch data from table A
//inserts data to Table B using timestamps got from Table A
//updates timestamp of Table A
}
Failed to Release mocks can happen when your dependencies are not aligned. Since you are using Spring Boot, make sure to not bump major Mockito version, but rather use spring-boot-starter-test and correct version of Spring Boot parent that will bring aligned set of dependencies including Mockito.
If you are trying to mock static class using mockito, you will need the following dependency first. If you try to mock static class without this dependency it will throw that error
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
Then mock the static class by using
MockedStatic<YourStaticClass> yourStaticClass = mockStatic(YourStaticClass.class)
Also make sure whether you are using the correct dependencies in your pom
Try adding #ExtendWith(MockitoExtension.class) on top of the test class and removing MockitoAnnotations.initMocks(this); from setUp method.
In IntelliJ, with a Springboot project (2.6.6) using JUnit 5, given the following test class, IntelliJ doesn't display exceptions occuring in the #BeforeAll method.
#ExtendWith(SpringExtension.class)
public class SpringTest {
private Object OBJECT = new Object();
#BeforeAll
public static void before() {
throw new RuntimeException("SpringTest.RuntimeException"); // replace by actual business code
}
#Test
public void test() {
// Doesn't matter
assertNotNull(this.OBJECT);
}
Running the class within IntelliJ (only this class)
Running the package of the test
When the #BeforeAll method is more complex, it's hard to understand that an exception occured, until you run the whole test package by chance.
In JUnit 4 with a #Before method, IntelliJ was showing test failure, with the stacktrace of the exception (which makes things easier to debug).
My pom.xml only dependencies are spring-boot-starter & spring-boot-starter-test.
Is this a bug / Is there any solution to reproduce the old behaviour ?
Stack:
Spring boot 2.6.6 / JUnit 5
IntelliJ IDEA 2022.1 Build #IU-221.5080.210
OpenJDK_x64Temurin_11.0.14.1_1 / Maven-3.8.4
Edit
As pointed out in the comment, to reproduce #Before of JUnit4, you should use #BeforeEach in Junit 5. In this case, IntelliJ will behave as before and display exceptions even when running only the given test class.
For the #BeforeAll, question is still pending.
Edit 2
A bug has been opened for the #BeforeAll exceptions: https://youtrack.jetbrains.com/issue/IDEA-292662
Bug resolved in IntelliJ 2022.1.1 Preview.
See YouTrack: IDEA-292662
I have the following simple code. I have a class (TestClass) and I want to test "someMethod". There is an external static method which is called by my "someMethod".
I want to Powermock that static method to return me some dummy object.
I have the #PrepareForTest(ExternalClass.class) in the begining, but when I execute it gives the error:
The class ExternalClass not prepared for test.
To prepare this class, add class to the '#PrepareForTest' annotation.
In case if you don't use this annotation, add the annotation on class or method level.
Please help me to point out what is wrong with the way I have used #PrepareForTest
#RunWith(PowerMockRunner.class)
#PrepareForTest(ExternalClass.class)
public class xyzTest {
#Mock
private RestTemplate restTemplate;
#Mock
private TestClass testClass;
#BeforeClass
private void setUpBeforeClass() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSuccessCase() {
Boolean mockResponse = true;
ResponseEntity<Boolean> response = new ResponseEntity<Boolean>(mockResponse, HttpStatus.OK);
SomeClass someClass = new SomeClass("test", "1.0.0", "someUrl", "someMetaData");
PowerMockito.mockStatic(ExternalClass.class);
Mockito.when(restTemplate.postForEntity(any(String.class), any(String.class), eq(Boolean.class))).thenReturn(response);
Mockito.when(ExternalClass.getSomeClass(any(String.class))).thenReturn(someClass);
Boolean result = testClass.someMethod("test");
Assert.isTrue(result);
Mockito.verify(restTemplate, times(1)).postForObject(any(String.class), any(String.class), any());
}
}
Make sure you add #RunWith(PowerMockRunner.class) to the top of your class as well.
::edit:: two years later...
Don't ever use PowerMockito, you shouldn't need to.
If you do need to, you have most likely broken the SOLID principles and your design is wrong.
Fix your design instead.
As with the last answer, my problem was also mixing the Test annotation from TestNG instead of Junit Test.
import org.junit.Test; // works
import org.testng.annotations.Test // did not work
Very abstruse error and I spent more than 5 hrs debugging :(
For those trying to get this working with Junit 5, If your using the powermock-module-junit4 beta release which claims to be compatible with 4+, the library will still not recognize:
import org.junit.jupiter.api.Test;
and it will throw a:
org.powermock.api.mockito.ClassNotPreparedException
when #PrepareForTest is applied on the class you want to static mock. If you want to use PowerMock, you will have to go back to Junit 4 or create a MockWrapper for your static method at this time.
PowerMock 2.0: Github Roadmap
While the top-rated answer here is correct without a doubt, this does not answer the question of why is that needed; or, for example, why the same thing would not work with adding #RunWith(MockitoJUnitRunner.class).
The thing is PowerMockRunner uses instrumentation API under the hood, via
javassist library, this allows to alter the classes, like remove final or mock static (non-compile time constants).
In the process of modifying (instrumenting) a certain class, they add an interface to that, called PowerMockModified. It is a marker interface that denotes that a certain byte-code instrumentation took place. Later in the code, they simply check if the class that you use in #PrepareForTest was actually instrumented in some way or not, via such a method:
private boolean isModifiedByPowerMock() {
return PowerMockModified.class.isAssignableFrom(this.type);
}
In turns out that PowerMockRunner does some instrumentation, while MockitoJUnitRunner does not; thus the error you get.
I had the same error, resolved this by adding
#Rule
public PowerMockRule rule = new PowerMockRule();
inside the test class.
If above answers don't work try extends PowerMockTestCase. This trick worked for me.
Example:
public class xyzTest extends PowerMockTestCase
check if import org.junit.Test; package has imported and not that api jupiter one.
I had the same error but resolved it. My problem was that I included powermock-module-junit4 but included my test annotation from TestNG instead of Junit.
I had the same error. I was using TestNG to run the tests. I had to use the following method to fix the above issue.
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
For testNG there are 2 options as follows :
Using ObjectFactory as below:
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
Test class extending extends org.powermock.modules.testng.PowerMockTestCase
My gradle was using Junit 5.
test {
useJUnitPlatform()
}
I was able to debug this. By having breakpoints in PowerMockRunner methods.
It was not invoked. Moreover JUnit 5 is not supported with PowerMockito.
Looks like JUnit5 runs without #ExtendWith.
Make sure you are using powermock2. I had this problem when I was using powermock.
Use
import org.powermock2.api.mockito.PowerMockito;
I have a Gradle based Java project were I now want to mock a private method using PowerMock. The problem is that I am not able to use the PowerMockRunner as I always get the following exception when I add the #RunWith(org.powermock.modules.junit4.PowerMockRunner.class) annotation.
Error:
org.powermock.reflect.exceptions.FieldNotFoundException: Field 'fTestClass' was not found in class org.junit.internal.runners.MethodValidator.
at org.powermock.reflect.internal.WhiteboxImpl.getInternalState(WhiteboxImpl.java:581)
at org.powermock.reflect.Whitebox.getInternalState(Whitebox.java:308)
at org.powermock.modules.junit4.internal.impl.testcaseworkaround.PowerMockJUnit4MethodValidator.validate TestMethods(PowerMockJUnit4MethodValidator.java:79)
at org.powermock.modules.junit4.internal.impl.testcaseworkaround.PowerMockJUnit4MethodValidator.validate InstanceMethods(PowerMockJUnit4MethodValidator.java:49)
at org.junit.internal.runners.MethodValidator.validateMethodsForDefaultRunner(MethodValidator.java:51)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.validate(PowerMockJUnit44RunnerDelegateImpl.java:108)
...
This are my test dependencies:
testCompile 'junit:junit:4.+',
'org.powermock:powermock-core:1.5.6',
'org.powermock:powermock-module-junit4:1.5.6',
'org.powermock:powermock-api-mockito:1.5.6'
The test itself fails also when completely empty (initialization error):
#RunWith(PowerMockRunner.class)
public class SomeTest {
#Test
public void testSomething() {
}
}
Any ideas what might be wrong? Other tests using PowerMock are working fine (none of them uses the PowerMockRunner).
Greetings and thanks for any help!
Ben
This is a bug that occurs when you use JUnit 4.12 and PowerMock < 1.6.1. The problem is solved in PowerMock 1.6.1. Please update your dependencies accordingly
testCompile 'junit:junit:4.12',
'org.powermock:powermock-core:1.6.1',
'org.powermock:powermock-module-junit4:1.6.1',
'org.powermock:powermock-api-mockito:1.6.1'
If you cannot upgrade PowerMock then you can use JUnit 4.11.
testCompile 'junit:junit:4.11',
'org.powermock:powermock-core:1.5.6',
'org.powermock:powermock-module-junit4:1.5.6',
'org.powermock:powermock-api-mockito:1.5.6'
Could you please add further lines of the stacktrace, which uncover more details about the problem.
There has been a bug logged against PowerMock: https://code.google.com/p/powermock/issues/detail?id=531
It appears that JUnit changed some of its internal field names that PowerMock was accessing via reflection, thus breaking the ability for PowerMock to properly inject itself.
Check what Stefan said, and above that you also need to add
#PrepareForTest({<The class/es you are Mocking>, ...})
without the prepare for test, PowerMockRunner won't know which class is mocked.
There may also exist dependencies on classpath that override a JUnit specific class which contains JUnit's version. This leads to incorrect version comparison results in PowerMock. For instance, I had com.google.android.tools:dx:1.7 on classpath (came from hunspell library). It overrides following method return result:
junit.runner.Version.id() => "3.8.1"
Usually it should return something like "4.12" or "4.11" etc.
I am trying to just run a simple test case. I have the following method.
public static void run(String[] args) throws Throwable {
CommandLineArguments opts = CommandLineOptionProcessor.getOpts(args);
}
I will continue to build this method / test case as I go. However I just wanted to make sure a simple test case worked first. So I wrote the following test.
#Test
public void testRun() {
String[] args = {"--arg1", "value", "--arg2", "value2"};
mockStatic(CommandLineOptionProcessor.class);
expect(CommandLineOptionProcessor.getOpts(args));
EasyMock.replay(CommandLineOptionProcessor.class);
}
After that I get the following error:
java.lang.IllegalStateException: no last call on a mock available
I read some of the other posts on StackOverflow but their solution seemed to be that they were using PowerMock with Mockito. I am using Powermock and Easymock, so that should not be the problem.
I followed Rene's advice and added the following to the top of my class.
#PrepareForTest(CommandLineOptionProcessor.class)
#RunWith(PowerMockRunner.class)
public class DataAssemblerTest {
I fixed the previous error. But now I have this error.
java.lang.IllegalArgumentException: Not a mock: java.lang.Class
at org.easymock.internal.ClassExtensionHelper.getControl(ClassExtensionHelper.java:61)
at org.easymock.EasyMock.getControl(EasyMock.java:2172)
at org.easymock.EasyMock.replay(EasyMock.java:2074)
.
.
.
Any ideas on what could be causing this would be great.
Did you annotate the test class with #RunWith(PowerMockRunner.class) and #PrepareForTest(CommandLineOptionProcessor.class)?
#RunWith(PowerMockRunner.class)
#PrepareForTest(CommandLineOptionProcessor.class)
public class TestClass {
#Test
public void testRun(){
You need the #PrepareForTest(CommandLineOptionProcessor.class) at the test class level. See the Powermock doc:
Use the #PrepareForTest(ClassThatContainsStaticMethod.class) annotation at the class-level of the test case.
Also ensure that the required libraries are on the test classpath.
In your case the javassist library is missing. Put it on the classpath. Maybe some other libs are also missing... we will see.
If you get
java.lang.IllegalArgumentException: Not a mock: java.lang.Class
then you are using EasyMock.replay(), but you must use PowerMock.replay()
EasyMock.expectLastCall()
or
EasyMock.expectLastCall().anyTimes()
or
EasyMock.expectLastCall().andAnswer(..)
is not present in your code, must be after the method you want to test
this is in case your test method is a void method.
otherwise you can use :
expect(CommandLineOptionProcessor.getOpts(args)).andReturn(object);
also please add this to you test class :
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory( );
}