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

6

14

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!

Kaveri answered 7/5, 2021 at 9:13 Comment(3)
You have conflict in your dependencies. My guess (I have no pc at hand to check): spring-boot-starter-test:2.4.2 pulls in Mockito 3.x, and you drop some parts of it to 2.x. Learn how to view and debug dependencies in gradle: docs.gradle.org/current/userguide/… simple technique is to display all resolved versions and eyeball them for mismatches.Headboard
LardinoisJosse did you remember how you have resolved it? I am also having the same issueHellenism
@Hellenism I just made a whole different testKaveri
O
14

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>
Oxbow answered 27/6, 2021 at 0:18 Comment(1)
thanks, its working in my case just by bumping up mockito-core version to 3.11.2 without exclusionsGuest
S
7

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

Sextan answered 4/8, 2021 at 19:18 Comment(1)
I am confused with this answer Is simply updating mockito-core version to 3.7.7 in the pom.xml enough to fix the problem?Dianadiandra
G
2

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).

Gavriella answered 28/9, 2021 at 16:33 Comment(0)
S
0

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

Semifinalist answered 27/10, 2021 at 7:24 Comment(0)
D
0

This has to be related to the conflicting Mockito 4 jar in your classpath. Check your Mockito dependencies by using the below command and make sure that you are not using any overriding Mockito 4 jars.

 mvn dependency:tree -Dincludes=:mockito-*
Dykes answered 5/5, 2023 at 10:26 Comment(0)
M
0

I got a similar error when trying to execute a method on a Mockito.spy where I hadn't done Mockito.doReturn on one of the class's methods.

Marmara answered 26/7, 2024 at 7:4 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.