@MockK或mockk()

5
在使用Mockk进行Android单元测试时,声明依赖项时使用的符号有什么区别吗?
class Test {
    private val x: X = mockk()

    private val test = TestClass(x)
...
}

或者
class Test {
    @MockK
    private lateinit var x: X

    @InjectMockKs
    private lateinit var test: TestClass
    
    @Before
    fun setup() {
        MockKAnnotations.init(this)
    }
...
}

1
你的意思是什么?是指性能上的差异还是结果上的差异? - ChristianB
任何@ChristianB,使用其中一个有什么区别吗?还是它们只是阅读相同内容的好方式? - Canato
doc中可以看到,"它只是使模拟的创建更简单"。因此,您可以使用MockKAnnotations.init(this, relaxUnitFun = true)来放松所有模拟,而不是为每个模拟单独执行mockk(relaxed = true) - ChristianB
3个回答

6

来自MockK项目

两种实现方式没有区别,它们是等价的。

一般来说,当您需要在代码中动态声明模拟对象时,或者如果您需要使单个模拟对象的单元函数放松(在这种情况下,可以使用mockk(relaxUnitFun = true)构建它),则可以使用mockk()。

如果您的模拟对象具有相同的行为,那么可以使用注释版本。


4
我建议在测试中使用mockk()和“天真”的构造函数依赖注入,而不是使用注释。原因如下:
  1. mockk() builder允许您定义不可变的val变量,这更安全,高效且更好*(从整个软件开发的角度来看),而使用@Mockk时,您应该使用var关键字;

  2. @InjectMockKs并不像它看起来那么酷。我曾在一个项目中遇到了与Mockito相同的问题。我的队友在构造函数参数的中间删除了一个类依赖项,构建并运行了代码,但忘记修复并在本地运行测试。他推送了这些更改,但随后我们在“运行测试”流水线阶段中遇到了一个指向无处的NPE的错误。我们花了一些额外的时间最终找到了问题,这是因为:

Mockito将尝试按照以下顺序仅通过构造函数注入、属性注入或setter注入来注入模拟。如果以下任何策略失败,则Mockito不会报告失败;即您必须自己提供依赖项。

https://www.javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/InjectMocks.html


1
如果您的 TestClass 的依赖关系将要改变,使用注解会更好。
因为您只需要添加/删除一个 @MockK,而不需要关心目标类的构造函数。

原文

@ExtendWith(MockKExtension::class)
class Test {
    @MockK
    private lateinit var x: X

    @InjectMockKs
    private lateinit var test: TestClass
}

TestClass添加一个依赖项

@ExtendWith(MockKExtension::class)
class Test {
    @MockK
    private lateinit var x: X

    @MockK
    private lateinit var y: Y  // <1> Just add this

    @InjectMockKs
    private lateinit var test: TestClass  // <2> Don't need to add the changed dependency into it's constructor
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接