问题描述
我正在将代码库迁移到Java 11和JPMS / Jigsaw,并且在模拟时遇到了一些麻烦。
这是我要运行的测试。
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));
}
}
在Eclipse中运行此测试时,该测试通过了,但是当我通过maven运行该测试时,它失败了,因为Mockito无法使用反射找到某些资源。
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"
我正在使用Surefire 3.0.0-M5,junit 5.7.0和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>
不用说,在使用JPMS进行模块化之前,此方法在maven中效果很好。
我已经读过Testing in the modular world,并尝试过使用junit-platform-maven-plugin来替代surefire,但在使用Mockito时遇到了类似的问题。
我们将不胜感激。
解决方法
TL; DR —您需要配置Surefire插件以将--add-opens
选项传递给 java
当它运行您的测试时...
--add-opens
如果必须允许类路径上的代码进行深层反思来访问非公共成员,请使用
--add-opens
运行时选项。某些库进行深层反射,表示
setAccessible(true)
,因此它们可以访问所有成员,包括私有成员。您可以使用--add-opens
命令行上的java
选项授予此访问权限...
尽管我无法完全按照您的问题中的错误消息来重现100%,但我仍然能够产生几乎相同的错误消息。它和您的相似,足以使我和您的根本原因相同(和解决方案)。
In this demo that you can download and build,我解决了遇到的错误…
…
<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。随意修改它,但您认为合适。