使用 Mockito 在 Android 中进行单元测试
大多数类都有依赖关系,方法经常将工作委托给其他类中的其他方法,我们称之为类依赖关系。如果我们只是使用 JUnit 对这些方法进行单元测试,我们的测试同样会依赖于它们。所有其他依赖项都应该独立于单元测试。结果,我们简单地模拟依赖类并测试主类。 Mockito 是一个有味道的模拟框架。它有一个干净简单的 API,可以让你构建漂亮的测试。 Mockito 中的测试非常易读,并且提供了清晰的验证错误,因此您不会宿醉。现在,让我们看一个如何使用 mockito 的示例。
例子
我们首先将依赖项添加到应用程序。文件分级:
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.19.0'
object Operators {
add(m: Int, n: Int): Int = m + n
subtract(n: Int, m: Int): Int = n - m
multiply(c: Int, a: Int): Int = c * a
divide(l: Int, d: Int): Int = l / d
}
下面还有计算器类:
Kotlin
class GfGCalculator(private val operators: Operators) {
fun addTwoNumbers(ab: Int, ba: Int): Int = operators.add(ab, ba)
fun subtractTwoNumbers(ac: Int, bc: Int): Int = operators.subtract(ac, bc)
fun multiplyTwoNumbers(ad: Int, bd: Int): Int = operators.multiply(ad, bd)
fun divideTwoNumbers(aa: Int, ba: Int): Int = operators.divide(aa, ba)
}
Kotlin
@RunWith(MockitoJUnitRunner::class)
class CalculatorTestGfG {
}
Kotlin
@RunWith(MockitoJUnitRunner::class)
class CalculatorTestGfG {
lateinit var calc: Calculator
@Before
fun someSetup() {
calc = Calculator(/** your operators here **/)
}
}
Kotlin
@RunWith(MockitoJUnitRunner::class)
class CalculatorTestGfG {
@Mock
lateinit var ops: Operators
lateinit var calc: Calculator
@Before
fun someSetup() {
calc = Calculator(operators)
}
}
Kotlin
package com.geeksforgeeks.calc
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnitRunner
@RunWith(MockitoJUnitRunner::class)
class CalculatorTest {
@Mock
lateinit var ops: Operators
lateinit var calc: Calculator
@Before
fun someSetup() {
calc = Calculator(ops)
}
@Test
fun givenValidInput_whenAdd_shouldCallAddOperator() {
val aa = 11
val ba = 21
calculator.addTwoNumbers(aa, ba)
verify(operators).add(aa, ba)
}
@Test
fun givenValidInput_whenSubtract_shouldCallSubtractOperator() {
val ac = 11
val bc = 21
calc.subtractTwoNumbers(ac, bc)
verify(ops).subtract(ac, bc)
}
@Test
fun givenValidInput_whenMultiply_shouldCallMultiplyOperator() {
val av = 11
val bv = 21
calc.multiplyTwoNumbers(av, bv)
verify(ops).multiply(av, bv)
}
@Test
fun givenValidInput_whenDivide_shouldCallDivideOperator() {
val ap = 11
val bp = 21
calc.divideTwoNumbers(ap, bp)
verify(ops).divide(ap, bp)
}
}
Calculator 的主要函数Object() { [native code] } 将运算符对象作为参数。因此,Calculator 类中的函数返回运算符函数作为返回参数。现在,让我们开始测试 Calculator 类。我们将在 test 文件夹中构建一个名为calculator 的包,就像我们在Java文件夹中所做的那样。
科特林
@RunWith(MockitoJUnitRunner::class)
class CalculatorTestGfG {
}
我们没有开发 OperatorsTest,因为我们只需要在这里测试 CalculatorTest。 MockitoJUnitRunner::class 在这里注解,表示它提供了一个 Runner 来运行测试。我们现在将设置计算器类。
科特林
@RunWith(MockitoJUnitRunner::class)
class CalculatorTestGfG {
lateinit var calc: Calculator
@Before
fun someSetup() {
calc = Calculator(/** your operators here **/)
}
}
运算符必须在构造中传递。因此,我们不会创建一个运算符对象,因为我们希望单独运行测试,这样即使 Operator 崩溃,也不会影响 CalculatorTest 测试。我们只需要使用 Operator 类的调用方法与外界进行通信。此外, @Before 意味着我们必须在运行测试之前设置依赖项。
科特林
@RunWith(MockitoJUnitRunner::class)
class CalculatorTestGfG {
@Mock
lateinit var ops: Operators
lateinit var calc: Calculator
@Before
fun someSetup() {
calc = Calculator(operators)
}
}
使用@Mock 注解,我们可以模拟 Mockito 中的任何类。通过模拟特定的类,我们创建了该类的模拟对象。在上面的代码中模拟了运算符,为 A Calculator 提供依赖项。现在我们将创建两个变量 a 和 b,其值为 12,21,并调用它们。
calc.addTwoNumbers(ab, ba)
我们只会使用,来查看是否从模拟类调用了正确的函数。
verify(operators).add(ab, ba)
验证表示您想查看模拟对象的特定方法是否已被调用。
这将执行测试并产生一个输出,指示测试是通过还是失败。因为我们使用了正确的函数,所以在我们的案例中测试通过了。我们的测试将失败,因为我们从 Calculator 类中调用 addNumbers,然后从假运算符中减去。
这就是我们如何在我们的应用程序中使用 Mockito 来执行单元测试。现在,为了测试所有的功能,编写并运行下面的代码
科特林
package com.geeksforgeeks.calc
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnitRunner
@RunWith(MockitoJUnitRunner::class)
class CalculatorTest {
@Mock
lateinit var ops: Operators
lateinit var calc: Calculator
@Before
fun someSetup() {
calc = Calculator(ops)
}
@Test
fun givenValidInput_whenAdd_shouldCallAddOperator() {
val aa = 11
val ba = 21
calculator.addTwoNumbers(aa, ba)
verify(operators).add(aa, ba)
}
@Test
fun givenValidInput_whenSubtract_shouldCallSubtractOperator() {
val ac = 11
val bc = 21
calc.subtractTwoNumbers(ac, bc)
verify(ops).subtract(ac, bc)
}
@Test
fun givenValidInput_whenMultiply_shouldCallMultiplyOperator() {
val av = 11
val bv = 21
calc.multiplyTwoNumbers(av, bv)
verify(ops).multiply(av, bv)
}
@Test
fun givenValidInput_whenDivide_shouldCallDivideOperator() {
val ap = 11
val bp = 21
calc.divideTwoNumbers(ap, bp)
verify(ops).divide(ap, bp)
}
}
GeekTip: Mockito cannot directly test final/static classes because all Kotlin classes are final. We need to set up mockito-extensions in order to run tests on final classes.