最终 class 方法未按需要使用 Mockito 2 进行测试

Final class method not getting tested as desired with Mockito 2

Mockito 2 docs中所述,我们现在可以模拟最终classes,所以我尝试在一个简单的项目中这样做,但结果并不合适。 这是我的项目结构

这是 org.mockito.plugins.MockMaker 文本文件

mock-maker-inline

这是一个演示 activity 用于测试

class LoginActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
    }

    private fun onLoginPressed(email:String, password:String){

    }

     fun isEmailValid(email: String):Boolean{
        return true
    }
}

这里是测试class

class LoginActivityTest{

    @Test
    fun checkLoginValidity(){
        val lognActivity = Mockito.mock(LoginActivity::class.java)
        assert(lognActivity.isEmailValid("yuo"))
    }
}

测试应该已经通过了,因为我总是返回 true,但这是我得到的结果。

我也标记和取消标记资源目录作为测试资源根目录,但实际上没有发生任何事情。

你能指出我哪里错了吗?

Mocking final (Kotlin) classes 和 Mockito 工作正常,你的设置显然是正确的(如果 mocking Activity 失败,你会得到一个错误)。您尝试测试的方式有问题。

Mockito 用于模拟要测试的 class 的 依赖项 ,而不是要测试的 class 本身。

你在那里做的是嘲笑你的 LoginActivity,然后断言它 return 有一些价值。对于 return 和 boolean 类似 isEmailValid(...) 的方法,默认为模拟 returns false。 你不测试模拟,那没有意义。您想要测试被测 class 的 'real' 实例。

如果您想测试 Activity,您只需使用 val classToTest = LoginActivity() 创建一个,然后执行您的 assert

这可能(不确定)适用于这种非常简单的情况,但通常您不会对 Activity 进行单元测试,因为有太多 Android 特定的东西在进行,比如膨胀布局(setContentView),这在单元测试中不起作用。

这就是为什么像 MVP 或 MVVM 这样的概念越来越受欢迎,将尽可能多的逻辑从 Android-class 中移开,例如 Activity,然后使其可测试。

对于你的情况,为了让你开始,你可以写一个 EmailChecker class 你是。然后在你的 Activity 中使用来检查电子邮件 String 和 b。可以用单元测试更好的测试。

你嘲笑了你的 Activity class,所以它的所有方法总是 returns "default" 值(booleanfalse) .你需要说 Mockito 来调用 class.

的真实方法
`when`(lognActivity.isEmailValid(ArgumentMatchers.any() ?: ""))
    .thenCallRealMethod()

顺便说一句,最好只将该解决方案用于抽象 classes,因为您不能用其他方法创建它的实例。如果你的 class 不是抽象的,就创建它(为了 Activity 测试更好地使用 specific tools)。