NoSuchMethodError: org.mockito.internal.runners.RunnerFactory.createStrict - java

I am using latest versions of JUnitParams, junit and mockito-all.
testCompile group: 'pl.pragmatists', name: 'JUnitParams', version: '1.1.1'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'org.mockito', name: 'mockito-all', version: '2.0.2-beta'
I keep getting NoSuchMethodError when running a JUnit test with annotation #RunWith(MockitoJUnitRunner.class).
java.lang.NoSuchMethodError: org.mockito.internal.runners.RunnerFactory.createStrict(Ljava/lang/Class;)Lorg/mockito/internal/runners/InternalRunner;
at org.mockito.junit.MockitoJUnitRunner.<init>(MockitoJUnitRunner.java:154)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
What can be the problem that triggers NoSuchMethodError exception?
Code:
#RunWith(MockitoJUnitRunner.class)
public class MockTest {
#Mock
ServletUriComponentsBuilder servletUriComponentsBuilder;
#Before
public void setup() {
servletUriComponentsBuilder = mock(ServletUriComponentsBuilder.class);
}
#Test
public void shouldGenerateUrl() {
when(servletUriComponentsBuilder.fromUriString(anyString()).build().toString())
.thenReturn("test");
Assert.assertEquals("my message", "test", "test");
}
}

mockito-core
You have Mockito 1.x and 2.x on your classpath. I think that is because you have a dependency to mockito-all:2.0.2-beta and some of your other dependencies has a transitive dependency to mockito-core:1.x.
You should never use mockito-all with a build system that does your dependency management. Instead use
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.0.2-beta'
or even a more current version (see The Central Repository)
Mockito documentation: https://github.com/mockito/mockito/wiki/Declaring-mockito-dependency
Please tell me, if this does not solve the problem.
Creation of mocks
This is not the cause of your problem but maybe helpful, too. You are creating the ServletUriComponentsBuilder twice. First the MockitoRunner creates it because of the #Mock annotation and then you override it with a new mock in you setup method. So either you do
#RunWith(MockitoJUnitRunner.class)
public class MockTest {
#Mock
ServletUriComponentsBuilder servletUriComponentsBuilder;
#Test
...
or you do
public class MockTest {
ServletUriComponentsBuilder servletUriComponentsBuilder;
#Before
public void setup() {
servletUriComponentsBuilder = mock(ServletUriComponentsBuilder.class);
}
#Test
...
You may even do this shorter
public class MockTest {
ServletUriComponentsBuilder servletUriComponentsBuilder
= mock(ServletUriComponentsBuilder.class);
#Test
...

Related

Gradle not seeing "log" variable definition?

Gradle v7.3.3
I'm trying to use the The Java Platform Plugin, and I have this so far in my platform build.gradle file
artifactId = "my-java-platform"
group = "com.mycompany.platform"
version = "1.0.0"
dependencies {
constraints {
...
api "org.slf4j:slf4j-log4j12:1.7.9"
api "org.projectlombok:lombok:1.16.18"
...
}
}
I did a ./gradlew publishToMavenLocal and see the resulting pom.xml file with those 2 dependencies.
Then in my application's build.gradle file I have
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
implementation platform(group: "com.company.platform", name: "my-java-platform", version: "1.0.0")
annotationProcessor platform(group: "com.company.platform", name: "my-java-platform", version: "1.0.0")
compileOnly group: "org.slf4j", name: "slf4j-log4j12"
compileOnly group: "org.projectlombok", name: "lombok"
...
}
One of my applications source code has
package com.mycompany.common
import java.util.TimeZone;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jsr310.JSR310Module;
import lombok.extern.slf4j.Slf4j;
#Slf4j
public class ObjectMapperConfiguration {
private static ObjectMapper objectMapper;
/**
* Static only
*/
private ObjectMapperConfiguration() {}
/**
* Work with Spring to configure the ObjectMapper
*/
public static ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
objectMapper = builder.createXmlMapper(false).build();
configureObjectMapper(objectMapper);
log.info("The ObjectMapperConfiguration has run");
return objectMapper;
}
...
}
But I get
$ ./gradlew clean build
> Task :compileJava FAILED
/Users/.../src/main/java/com/company/common/ObjectMapperConfiguration.java:39: error: cannot find symbol
log.info("The ObjectMapperConfiguration has run");
^
symbol: variable log
location: class com.company.common.ObjectMapperConfiguration
I understand that the log variable is defined in the #Slf4j annotation? If so why am I getting the error? Thanks!
The Lombok magic is implemented via an annotation processor.
See here for the recommended Lombok Gradle config
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.22'
testCompileOnly 'org.projectlombok:lombok:1.18.22'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.22'
}
The application's build.gradle file, the one that uses the platform, should look like this
dependencies {
implementation platform(group: "com.mycompany.platform", name: "my-java-platform", version: "1.0.0")
annotationProcessor platform(group: "com.company.platform", name: "my-java-platform", version: "1.0.0")
annotationProcessor group: "org.projectlombok", name: "lombok"
...
}

How to fix this error: java.lang.NoSuchMethodError: 'java.lang.AutoCloseable org.mockito.MockitoAnnotations.openMocks(java.lang.Object)'

So I am getting this error in my Spring boot Gradle project:
'java.lang.AutoCloseable org.mockito.MockitoAnnotations.openMocks(java.lang.Object)'
java.lang.NoSuchMethodError: 'java.lang.AutoCloseable org.mockito.MockitoAnnotations.openMocks(java.lang.Object)'
And I cannot seem to fix it. I have searched for the answer but the only one I get is removing mockito-all from your dependencies, but I do not have that in my gradle.build file in the first place.
My build.gradle file:
plugins {
id 'org.springframework.boot' version '2.4.2'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id "org.sonarqube" version "3.0"
id 'jacoco'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '15'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.httpcomponents:httpcore:4.4.1'
compile 'org.apache.httpcomponents:httpclient:4.5'
implementation('io.jsonwebtoken:jjwt:0.2')
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compile 'junit:junit:4.12'
implementation 'org.modelmapper:modelmapper:2.4.1'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.eclipse.jgit:org.eclipse.jgit:5.4.2.201908231537-r'
/**
* JUnit jupiter with mockito.
*/
testCompile group: 'org.mockito', name: 'mockito-junit-jupiter', version: '2.19.0'
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.19.0'
testCompile group: 'org.springframework.security', name: 'spring-security-test', version: '5.1.6.RELEASE'
}
sonarqube{
properties{
property 'sonarjava.source', '1.8'
property 'sonar.java.coveragePlugin', 'jacoco'
property 'sonar.jacoco.reportPaths', 'build/reports/jacoco/test/jacocoTestReport.xml'
}
}
test {
useJUnitPlatform()
}
I can't seem to find a solution so I came to here, where some code god maybe can help me fixing my problem.
The file where I get this error on is a test class:
The test class:
package com.example.demo.Service;
import com.example.demo.DTO.PartyLeaderDto;
import com.example.demo.Model.PartyLeader;
import com.example.demo.Repository.PartyLeaderRepository;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import static org.mockito.Mockito.verify;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.modelmapper.ModelMapper;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
import static org.mockito.Mockito.when;
import static org.mockito.ArgumentMatchers.argThat;
#SpringBootTest
#AutoConfigureMockMvc
public class PartyLeaderServiceMockTest {
#Rule
public MockitoRule initRule = MockitoJUnit.rule();
#Mock
private PartyLeaderRepository partyLeaderRepository;
#Mock
private ModelMapper modelMapper;
#InjectMocks
private PartyLeaderService partyLeaderService; // this is like calling new PartyLeaderService(partyLeaderRepository, modelMapper);
#Test
void whenSavePartyLeader_thenCorrectPartyLeaderSaved() {
// given
var input = PartyLeaderDto.builder()
.name("Josse")
.apperance("Link of image")
.build();
// when
partyLeaderService.savePartyLeader(input);
// then
verify(partyLeaderRepository).save(argThat(entity ->
entity.getName().equals("Josse")
&& entity.getApperance().equals("Link of image")));
}
#Test
void whenGetPartyLeader_ShouldReturnCorrectLeaderData() {
// given
var partyLeaderEntity = PartyLeader.builder()
.name("Josse")
.apperance("Link of image")
.build();
var partyLeaderDto = PartyLeaderDto.builder()
.name("Josse")
.apperance("Link of image")
.build();
when(partyLeaderRepository.findById(3)).thenReturn(Optional.of(partyLeaderEntity));
when(modelMapper.map(partyLeaderEntity, PartyLeaderDto.class)).thenReturn(partyLeaderDto);
// when
var result = partyLeaderService.getPartyLeader(3);
// then
Assert.assertEquals(result, partyLeaderDto);
}
}
I get the same error on both of my tests.
Can anyone help me? Thanks in advance!
Issue was due to the jar conflicts
We need to exclude
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
</exclusion>
</exclusions>
</dependency>
And include
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.11.2</version>
</dependency>
After facing the same issue. Please look log trace.
java.lang.NoSuchMethodError: org.mockito.MockitoAnnotations.openMocks(Ljava/lang/Object;)Ljava/lang/AutoCloseable;
at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.initMocks(MockitoTestExecutionListener.java:83)
Finally got a solution:
In Mockito version 2 there is a MockitoAnnotations.initMock() method, which is deprecated and replaced with MockitoAnnotations.openMocks() in Mockito JUnit 5 version 3. The MockitoAnnotations.openMocks() method returns an instance of AutoClosable which can be used to close the resource after the test.
Manual Initialization
Before doing anything else, we have to add the Mockito dependency.
dependencies {
testImplementation('org.mockito:mockito-core:3.7.7')
}
The MockitoAnnotations.openMocks(this) call tells Mockito to scan this test class instance for any fields annotated with the #Mock annotation and initialize those fields as mocks.
Pros:
Easy to create mocks
Very readable
Cons:
Does not validate framework usage or detect incorrect stubbing
Automatic Mock Injection
We can also tell Mockito to inject mocks automatically to a field annotated with #InjectMocks.
When MockitoAnnotations.openMocks() is called, Mockito will:
Create mocks for fields annotated with the #Mock annotation
Create an instance of the field annotated with #InjectMocks and try to inject the mocks into it
Using #InjectMocks is the same as we did when instantiating an instance manually, but now automatic.
public class MockitoInjectMocksTests {
#Mock
private OrderRepository orderRepository;
private AutoCloseable closeable;
#InjectMocks
private OrderService orderService;
#BeforeEach
void initService() {
closeable = MockitoAnnotations.openMocks(this);
}
#AfterEach
void closeService() throws Exception {
closeable.close();
}
#Test
void createOrderSetsTheCreationDate() {
Order order = new Order();
when(orderRepository.save(any(Order.class))).then(returnsFirstArg());
Order savedOrder = orderService.create(order);
assertNotNull(savedOrder.getCreationDate());
}
}
Mockito will first try to inject mocks by constructor injection, followed by setter injection, or field injection.
Pros:
Easy to inject mocks
Cons:
Doesn’t enforce usage of constructor injection
For me, none of the workarounds mentioned here worked.
Updating mockito-core from 3.3.3 to 3.4.3 fixed the problem.
I think it is caused by the fact that the MockitoAnnotations.initMock() method is deprecated and has been replaced by MockitoAnnotations.openMocks() in Mockito JUnit 5 version 3.
On the other hand, it may be worthy to check the local Maven Repository and delete unnecessary jars that may cause conflict. But when applying this step, beware not to manually delete installed ones (or do a backup before the operation).
I've faced the same problem I've fixed it by using
Mockito.mock() method instead of #Mock.
I use spring-boot-starter-test v2.4.8 and mockito-core v2.21.0
In my case the error occurred because in initMocks method from MockitoTestExecutinListener class looks like this:
private void initMocks(TestContext testContext) {
if (hasMockitoAnnotations(testContext)) {
testContext.setAttribute(MOCKS_ATTRIBUTE_NAME, MockitoAnnotations.openMocks(testContext.getTestInstance()));
}
}
but in my case MockitoAnnotations have only initMocks() method, so the error.
In this case we need to make sure that hasMockitoAnnotations(testContext) is false.
In order to use #Mock I need to enable Mockito annotations, but I do not want this, therefore I used Mockito.mock().

How to run PowerMock v1.74 with java.net.InetAddress static method

I have been reading a lot about PowerMockito to mock static methods. So I have been trying to use v1 (not v2), although I don't really care which version of PowerMockito or testNG I use. I figure I missed some critical detail here in the configuration, but I am at a loss.
Using Oracle Java 1.8
subprojects.gradle:
testCompile group: 'org.testng', name: 'testng', version: '6.14.3'
testCompile group: 'org.powermock', name: 'powermock-module-testng', version: '1.7.4'
testCompile group: 'org.powermock', name: 'powermock-api-mockito', version: '1.7.4'
I checked my versioning of modules here
Test class
import org.mockito.*;
import org.mockito.invocation.*;
import org.mockito.stubbing.*;
import org.powermock.core.classloader.annotations.*;
import org.powermock.modules.testng.*;
import org.testng.*;
import org.testng.annotations.*;
import java.io.*;
import java.net.*;
import static org.powermock.api.mockito.PowerMockito.*;
#PrepareForTest({java.net.InetAddress.class})
public class testClass extends PowerMockTestCase {
#Test
public void exampleTest()
throws IOException, URISyntaxException, MyCustomException {
mockStatic(InetAddress.class);
// I use these three functions, so I think I have to mock them all?
when(InetAddress.getByName(Mockito.anyString()))
.thenReturn(InetAddresses.forString("111.0.0.111"));
when(InetAddress.getByAddress(Mockito.anyObject()))
.thenCallRealMethod();
when(InetAddress.getLocalHost()).thenCallRealMethod();
MyNewClass mnc = new MyNewClass();
mnc.someCodeUsingInetAddress();
}
This compiles and runs, but does not change the behavior of the function InetAddress.getByName() when called from someCodeUsingInetAddress().
Now I read here that I need to label the class with
#RunWith(PowerMockRunner.class). But IntelliJ won't let me import the PowerMockRunner.class from any of the possible sources, of which it is aware. Which also makes me wonder which one I should be trying to use.
org.testng.PowerMockRunner
org.testng.annotations.PowerMockRunner
org.powermock.modules.testng.PowerMockRunner
the list goes on...

ClassNotFoundException: org.jboss.naming.remote.client.InitialContextFactory when trying to load InitialContext

I'm testing (with JUnit) an rest service and to make shure everything goes as intended i need to use some EJB methods. Say, i have:
the class under test, wich is of no interest here;
testing class
public class UploadServiceTest {
private final String RemoteBeanLookupKey = "/project/dao/TaskManager!ru.project.dao.TaskManager";
#EJB private TaskManager taskManager;
#Before
public void startEverythingNeeded() throws Exception {
InitialContext ctx = null;
Properties jndiProp = new Properties();
InputStream testConfStream = getClass().getClassLoader().getResourceAsStream("jndi.properties");
jndiProp.load(testConfStream);
ctx = new InitialContext(jndiProp);
taskManager = ((TaskManager) ctx.lookup(RemoteBeanLookupKey));
}
#Test
public void blablabla(){
}
}
jndi.properties
java.naming.factory.initial=org.jboss.naming.remote.client.InitialContextFactory
java.naming.provider.url=http-remoting://localhost:8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
jboss.naming.client.ejb.context=true
remote.connection.default.username=admin
remote.connection.default.password=admin
gradle dependencies: testCompile group: 'org.wildfly', name: 'wildfly-ejb-client-bom', version: '8.2.0.Final', ext: 'pom', testCompile group: 'junit', name: 'junit', version: '4.11' and provided project(path: ':dao') (this is the module i want to get EJB from).
But when i try to run test, it fails with javax.naming.NoInitialContextException: Cannot instantiate class: org.jboss.naming.remote.client.InitialContextFactory
[Root exception is java.lang.ClassNotFoundException: org.jboss.naming.remote.client.InitialContextFactory]
Other similar questions on here and on the net suggest to add jboss-client to CLASSPATH, but i've looked into README near jboss-client in my distribution and it sayed not to act like this and to make a gradle dependency instead. So I did.
Another strange thing about this: I got code and properties from tests to another module in same project (written by another coder). I tried to run those tests and they work as intended. I copied everything and even more (gradle depency), but get this exception.
I've tried to simplify the code in order to illustrate, I may have something important missing. If needed, I can copy some more parts of setup and code.
I changed the dependency on ejb-client from testCompile group: 'org.wildfly', name: 'wildfly-ejb-client-bom', version: '8.2.0.Final', ext: 'pom' to testCompile 'org.wildfly:wildfly-ejb-client-bom:10.0.0.Final' and it started working. Not sure if it is helpfull.

Robolectric PowerMock java.lang.NoClassDefFoundError error while running a test

I want to integrate powermock to test firebase logic. I tried to run a test and got this:
java.lang.NoClassDefFoundError: org/mockito/cglib/proxy/MethodInterceptor
Here is my app.gradle:
testCompile 'junit:junit:4.12'
testCompile "org.powermock:powermock-module-junit4:1.7.0"
testCompile "org.powermock:powermock-module-junit4-rule:1.7.0"
testCompile "org.powermock:powermock-api-mockito:1.7.0"
testCompile "org.powermock:powermock-classloading-xstream:1.7.0"
testCompile "org.robolectric:robolectric:3.4.2"
testCompile 'org.mockito:mockito-core:2.1.0'
Here is my test:
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class)
#PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
#PrepareForTest({FirebaseAuth.class, FirebaseDatabase.class})
public class LoginTest {
#Before
public void setUp() {
PowerMockito.mockStatic(FirebaseAuth.class);
Mockito.when(FirebaseAuth.getInstance()).thenReturn(Mockito.mock(FirebaseAuth.class));
}
#Test
public void test() {
}
}
You are using 'org.mockito:mockito-core:2.1.0' with "org.powermock:powermock-api-mockito:1.7.0".
To use PowerMock with Mockito 2 the "org.powermock:powermock-api-mockito2:1.7.0" should be used.
You need the cglib library in your class path.
My solution is to always download a "complete" powermock ZIP from here. Those ZIP files contain everything you need in order to get going with PowerMock.

Categories

Resources