Mockito in maven using JPMS cannot access a member of class with modifiers “private”

无人久伴 提交于 2020-12-15 06:24:01

问题


I am migrating a codebase to Java 11 and JPMS / Jigsaw and am having some trouble with mocking.

This is the test I am trying to run.

import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class DbTest {

    @Mock
    private Connection connection;

    @Mock
    private PreparedStatement preparedStatement;

    @Captor
    private ArgumentCaptor<Timestamp> dateCaptor;

    @Test
    public void setTimestamp_instant() throws SQLException {
        Instant inputTime = Instant.parse("2018-03-12T10:25:37.386Z");
        when(connection.prepareStatement(anyString())).thenReturn(preparedStatement);
        PreparedStatement preparedStatement = connection.prepareStatement("UPDATE fakeTable SET time = ? WHERE TRUE");
        RowPack rowPack = new RowPack(preparedStatement, DatabaseType.MYSQL);
        rowPack.setTimestamp(inputTime);
        verify(preparedStatement).setTimestamp(anyInt(), dateCaptor.capture(), Mockito.any(Calendar.class));
    }
}

When running this test in Eclipse it passes but when I run it through maven it fails due to mockito being unable to find some resources using reflection.

org.mockito.exceptions.base.MockitoException: Problems setting field connection annotated with @org.mockito.Mock(name="", stubOnly=false, extraInterfaces={}, answer=RETURNS_DEFAULTS, serializable=false, lenient=false)
Caused by: java.lang.IllegalAccessException: class org.mockito.internal.util.reflection.ReflectionMemberAccessor cannot access a member of class foo.bar.DbTest (in module foo.bar) with modifiers "private"

I am using Surefire 3.0.0-M5, junit 5.7.0 and mockito 3.5.10.

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>

Needless to say this worked well in maven before switching to modularising with JPMS.

I have read Testing in the modular world and tried the junit-platform-maven-plugin as a replacement for surefire but ran into similar problems with mockito.

Help would be greatly appreciated.


回答1:


TL;DR — You need to configure the Surefire Plugin to pass the --add-opens option to java when it runs your test…

--add-opens

If you have to allow code on the class path to do deep reflection to access nonpublic members, then use the --add-opens runtime option.

Some libraries do deep reflection, meaning setAccessible(true), so they can access all members, including private ones. You can grant this access using the --add-opens option on the java command line…


Although I wasn't able to reproduce 100% verbatim the error message in your question, I was able to produce one that was pretty much the same. It was similar enough to yours, that I'm confident that the root cause (and the solution) of both mine and yours is the same.

In this demo that you can download and build, I resolved the error I got with…

…
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
    <configuration>
        …
        <argLine>add-opens foo.bar/foo.bar=ALL-UNNAMED</argLine>
        …
    </configuration>
</plugin>
…

Download and build the demo. Feel free to modify it however you see fit.



来源:https://stackoverflow.com/questions/64120676/mockito-in-maven-using-jpms-cannot-access-a-member-of-class-with-modifiers-priv

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!