Scala3.2+Scalatest3.2+Java18环境下如何Mock类?
Java 18环境下Mock Scala类的解决方案
问题背景
原有Scala测试代码运行正常:
@RunWith(classOf[JUnitRunner]) class IdentitySuite extends AnyFunSuite with Matchers { test("No Records returned") { assert(true) } }
添加EasyMock相关依赖后:
testing { suites { // Configure the built-in test suite test { // Use JUnit4 test framework useJUnit('4.13.2') dependencies { // Use Scalatest for testing our library implementation 'org.scalatest:scalatest_3:3.2.12' implementation 'org.scalatestplus:junit-4-13_3:3.2.12.0' implementation 'org.easymock:easymock:4.3' implementation 'org.scalatestplus:easymock-4-3_3:3.2.12.0' runtimeOnly 'org.scala-lang.modules:scala-xml_3:2.1.0' } } } }
尝试创建Mock对象时触发错误:
@RunWith(classOf[JUnitRunner]) class IdentitySuite extends AnyFunSuite with Matchers { test("No Records returned") { val cds = EasyMock.createMock(classOf[CoreDataSource]) assert(true) } }
错误信息:
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @40f9161a
无法降级到Java 15,需在Java 18环境下解决Mock问题。
解决方案
方案1:升级EasyMock到兼容高版本Java的版本
EasyMock 4.3版本对Java 9+模块系统的适配不足,升级到4.5及以上版本即可解决反射权限问题,同时同步升级对应的ScalaTestPlus集成库:
修改构建配置:
testing { suites { test { useJUnit('4.13.2') dependencies { implementation 'org.scalatest:scalatest_3:3.2.15.0' implementation 'org.scalatestplus:junit-4-13_3:3.2.15.0' implementation 'org.easymock:easymock:4.6' implementation 'org.scalatestplus:easymock-4-6_3:3.2.15.0' runtimeOnly 'org.scala-lang.modules:scala-xml_3:2.1.0' } } } }
方案2:添加JVM启动参数解除模块访问限制
如果暂时无法升级依赖,可通过JVM参数开放模块权限,允许EasyMock进行反射操作:
在构建配置中为测试任务添加JVM参数:
testing { suites { test { useJUnit('4.13.2') jvmArgs += [ "--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens=java.base/java.lang.reflect=ALL-UNNAMED" ] dependencies { implementation 'org.scalatest:scalatest_3:3.2.12' implementation 'org.scalatestplus:junit-4-13_3:3.2.12.0' implementation 'org.easymock:easymock:4.3' implementation 'org.scalatestplus:easymock-4-3_3:3.2.12.0' runtimeOnly 'org.scala-lang.modules:scala-xml_3:2.1.0' } } } }
方案3:替换为适配性更好的Mock库(如Mockito)
若上述方案均不适用,可换用Mockito,它对高版本Java和Scala的兼容性更优:
修改构建配置添加Mockito依赖:
testing { suites { test { useJUnit('4.13.2') dependencies { implementation 'org.scalatest:scalatest_3:3.2.12' implementation 'org.scalatestplus:junit-4-13_3:3.2.12.0' implementation 'org.mockito:mockito-core:4.8.1' implementation 'org.scalatestplus:mockito-4-6_3:3.2.12.0' runtimeOnly 'org.scala-lang.modules:scala-xml_3:2.1.0' } } } }
修改测试代码使用Mockito:
@RunWith(classOf[JUnitRunner]) class IdentitySuite extends AnyFunSuite with Matchers with MockitoSugar { test("No Records returned") { val cds = mock[CoreDataSource] assert(true) } }
内容的提问来源于stack exchange,提问作者Jackie
相关产品推荐
相关产品推荐

