Failed to release mocks - Mockito - java

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.

Related

IntellIj not displaying exceptions from #BeforeAll JUnit5

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

How to mock static method in Junit 5? [duplicate]

I want to mock a static method in JUnit 5. But unfortunately, JUnit 5 doesn’t support Mockito. Is there another method to achieve the same other than reverting back to JUnit 4?
From Mockito 3.4.0 (2020-07-10), it is possible to mock static methods out of the box even in JUnit 5, without any extension.
In the documentation, you can find an example: 48. Mocking static methods (since 3.4.0)
Important note: You need to use inline mock maker. So the dependency to use is not the core one:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.4.6</version>
<scope>test</scope>
</dependency>
Example:
Class under test:
package teststatics;
public class FooWithStatics {
public static Long noParameters() {
return System.currentTimeMillis();
}
public static String oneParameter(String param1) {
return param1.toUpperCase();
}
}
Test class:
package teststatics;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
public class FooWithStaticsTest {
#Test
void testStatic() {
// Before mock scope, usual behavior.
assertNotEquals(0L, FooWithStatics.noParameters());
assertNotEquals("yyy", FooWithStatics.oneParameter("xxx"));
// Mock scope
try (MockedStatic mocked = mockStatic(FooWithStatics.class)) {
// Mocking
mocked.when(FooWithStatics::noParameters).thenReturn(0L);
mocked.when(() -> FooWithStatics.oneParameter("xxx")).thenReturn("yyy");
// Mocked behavior
assertEquals(0L, FooWithStatics.noParameters());
assertEquals("yyy", FooWithStatics.oneParameter("xxx"));
// Verifying mocks.
mocked.verify(times(1), FooWithStatics::noParameters);
mocked.verify(times(1), () -> FooWithStatics.oneParameter("xxx"));
}
// After mock scope returns to usual behavior.
assertNotEquals(0L, FooWithStatics.noParameters());
assertNotEquals("yyy", FooWithStatics.oneParameter("xxx"));
}
}
The short answer is no, as the Mockito team is done with their work and is waiting for the JUnit team for an extension and are discussing here a lot.
With some overhead you can: As JUnit 5 provides support for running legacy JUnit 4, and there you can use Mockito. So you can create tests in Junit4 for these cases:
A sample project for migration setup with gradle and with mvn. From there I am using PowerMock 2.0 beta with Mockito 2.
The reason why Mockito doesn't provide static methods mocking at the moment is because of the common belief that static method shouldn't need to be mocked.
However, there is an open item for Mockito here that discusses the issue.
While this doesn't answer your question, in general it tells you why you shouldn't need the feature at all or will allow you to join the conversation with your ideas.
Make sure to have mockito-inline dependency in your POM file
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.6.28</version>
<scope>test</scope>
</dependency>
In my case I had to test scenario where exception thrown static method encode() of URLEncoder Class, so for that
try (MockedStatic theMock = mockStatic(URLEncoder.class)) {
theMock.when(() -> URLEncoder.encode("Test/11", StandardCharsets.UTF_8.toString()))
.thenThrow(UnsupportedEncodingException.class);
when(restClient.retrieveByName("Test%2F11")).thenReturn(null);
Assertions.assertThrows(ResponseStatusException.class, ()->service.retrieveByName("Test/11"));
}
We can mock a static method by JMockit.
JMockit is used for mocking the external dependencies outside the test boundary, similar to Mockito and other such mocking libraries.
The most important feature of JMockit is that it lets us mock anything, even the things that are hard to mock with other libraries such as constructors, static and final methods. It even allows mocking the member fields and initialization blocks as well.
Follow the below steps to enable JMockit:
The JMockit artifact is located in the central Maven repository, add the JMockit dependency in pom.xml
<!-- https://mvnrepository.com/artifact/org.jmockit/jmockit -->
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.49</version>
<scope>test</scope>
</dependency>
Mock the Class method in TestClass:
public class TestClass{
#Test
public void testMethod() {
new MockUp<ClassName>(){
#Mock
//mock the method here
};
}
}
Follow the tutorial to know more about how to use the JMockit.

PowerMock throw java.lang.ExceptionInInitializerError

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.

How does dependency injection work in Cucumber?

I have been trying to inject webdriver into the steps. I have used this instructions and it works well.
The idea is to inject WebDriver into steps classes as a service. At the initial step, you need to add the following dependency.
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-spring</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
There are three main classes which are involved in the dependency injection. Here we introduce them one by one.
BaseUtil
BaseUtil is the class which has an attribute for WebDriverof Selenium. The class is quite simple:
public class BaseUtil {
private WebDriver driver;
public WebDriver getDriver() {return driver;}
public void setDriver(WebDriver driver) { this.driver = driver;}
}
Hook
The Hook class contains #Before, #After. The method testInitialier() is responsible to load the the webDriver file and create an instance, while the method testTearDown() is responsible for closing the browser.
public class Hook extends BaseUtil{
BaseUtil base;
#Before
public void testInitializer(){
File file = new
File(IgniteTaskApplication.class.getClassLoader().getResource("driver/chromedriver.exe").getFile());
String driverPath=file.getAbsolutePath();
System.out.println("Webdriver is in path: "+driverPath);
System.setProperty("webdriver.chrome.driver",driverPath);
base.setDriver(new ChromeDriver());
}
public Hook(BaseUtil base) {
this.base = base;
}
#After
public void tearDownTest(){
base.getDriver().close();
}
}
Steps
And the steps class contains the steps which came from compiled features file. To compile the feature file in Eclipse you need to have Eclipse-Cucumber plugin installed in your Eclipse.
public class ClickButton_Steps extends BaseUtil{
BaseUtil base;
public ClickButton_Steps(BaseUtil base){
super();
this.base=base;
}
#When("^I clcik on the button$")
public void i_clcik_on_the_button() throws Throwable {
cb=new ClickButtonPage(base.getDriver());
cb.navigator();
}
// The other steps ...
}
How do i run it?
Open the feature file -> Run as -> Run with Junit
Question
I am wondering what is the order of running methods in a way which it leads to dependency injection?
I guess the order is as following:
Junit calls #Before method which is testInitializer()
The testInitializer()is in Hook class so it needs to make an instance of Hook class.
It leads to call the constuctor of the Hook class.
But, i cannot understand the rest of the steps. Maybe even it does not true at all. I mean, I have a functional code but i cannot explain how it works?
As I understand you correctly you use JUnit as a test framework with cucumber-spring. JUnit provides the following lifecycle.
When you annotate the method with annotation #Before that it will call this method before each test that you have.
As for #After could be used for cleaning resources and call after each test.
Your test flow when you run the test:
testInitializer
i_clcik_on_the_button
tearDownTest
In addition, you could use logging (slf4j) instead of System.out.println and it will be easier to track test flow.

Mockito asks to add #PrepareForTest for the class even after adding #PrepareForTest

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;

Categories

Resources