如何在Scala 2.x+scalatest环境中正确使用Mockito的@Mock注解
问题原因
你遇到的报错是两个核心错误共同导致的:
- 你标注了
@Mock的action字段被手动赋值为真实的Action实例,且没有初始化Mockito注解,@Mock完全没有生效,你后续操作的是真实对象而非Mockito生成的mock对象。Mockito的参数匹配器(如anyInt())仅能用于mock对象的打桩、验证场景,用在真实对象的方法调用上会直接抛出匹配器滥用异常。 - 你将打桩逻辑直接写在了类构造块中,Scala类构造块代码会在类初始化阶段执行,此时就算
@Mock配置正确,也可能还没完成mock实例注入,出现空指针或者配置失效问题。
正确配置步骤
1. 依赖引入(SBT示例)
首先引入ScalaTest和Mockito的整合依赖,避免兼容性问题:
libraryDependencies ++= Seq( "org.scalatest" %% "scalatest" % "3.2.15" % Test, "org.scalatestplus" %% "mockito-3-4" % "3.2.15.0" % Test )
2. 修正代码写法
方式1:混入MockitoSugar特质(推荐,适配ScalaTest)
import org.mockito.Mock import org.mockito.Mockito._ import org.mockito.ArgumentMatchers._ import org.scalatest.funsuite.AnyFunSuite import org.scalatestplus.mockito.MockitoSugar class Test1 extends AnyFunSuite with MockitoSugar { // 不要手动赋值,用var + 下划线占位,由Mockito注入mock实例 @Mock var action: Action = _ test("测试process方法返回值") { // 打桩逻辑写在测试用例内部 when(action.process(anyInt())).thenReturn("x") // 测试断言 assert(action.process(123) == "x") } }
方式2:手动初始化Mockito注解
如果不想引入整合依赖,也可以手动触发注解初始化:
import org.mockito.Mock import org.mockito.Mockito._ import org.mockito.ArgumentMatchers._ import org.mockito.MockitoAnnotations import org.scalatest.BeforeAndAfterEach import org.scalatest.funsuite.AnyFunSuite class Test1 extends AnyFunSuite with BeforeAndAfterEach { @Mock var action: Action = _ override def beforeEach(): Unit = { // 每个测试用例执行前初始化注解,保证mock实例隔离 MockitoAnnotations.openMocks(this) } test("测试process方法返回值") { when(action.process(anyInt())).thenReturn("x") assert(action.process(123) == "x") } }
注意事项
- 低版本Mockito请将
MockitoAnnotations.openMocks(this)替换为过时方法MockitoAnnotations.initMocks(this) - 不要给
@Mock标注的字段手动赋值,否则Mockito注入的mock实例会被你赋值的真实对象覆盖 - 打桩、验证逻辑不要写在类构造块中,优先放在测试用例内部或者
beforeEach/beforeAll钩子中
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

