带有Mock ViewModel的NoBeanDefFoundException,使用Koin,Espresso进行测试 [英] NoBeanDefFoundException with Mock ViewModel, testing with Koin, Espresso

查看:162
本文介绍了带有Mock ViewModel的NoBeanDefFoundException,使用Koin,Espresso进行测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试使用 Koin 作为DI工具进行简单的 Espresso 单元测试.这是我在 build.gradle

I have been trying to get a simple Espresso unit test work with Koin as DI tool. Here are the dependencies that I am using in build.gradle

    // testing with Koin
    // because of this
    // https://github.com/InsertKoinIO/koin/pull/604/commits/69391bc378bbb9007b9d82c46537e7d753be7ea3
    androidTestImplementation 'org.mockito:mockito-android:3.1.0'
    androidTestImplementation ("org.koin:koin-test:$koin_version") {
        exclude group: 'org.mockito'
    }

    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    // stuff like ActivityTestRule
    androidTestImplementation 'androidx.test:rules:1.2.0'
    // AndroidJUnit4
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    // test runner
    androidTestImplementation 'androidx.test:runner:1.2.0'

我的 ViewModel 声明

open class LoginViewModel(private val apiService: MockApiService) : ViewModel() {
..
..
}

这是它在活动"中的注入方式

here is how its injected in Activity

private val loginViewModel: LoginViewModel by viewModel()

我的自定义 TestRunner 以便实例化自定义 TestApplication

my custom TestRunner in order to have custom TestApplication instantiated

class MyTestRunner : AndroidJUnitRunner() {
    override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
        return super.newApplication(cl, TestApplication::class.java.name, context)
    }
}

TestApplication 类.我已经验证了调用测试时该测试类是否已初始化

TestApplication class. I have verified that this test class gets initialised when test is invoked

class TestApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        startKoin {
            androidLogger()
            androidContext(this@TestApplication)
            modules(emptyList())
        }
    }
}

这是我实际的 androidTest .一旦使用 NoBeanDefFoundException

Here is my actual androidTest. This fails as soon as activity is started with NoBeanDefFoundException

未找到"com.abhishek.mvvmdemo.onboarding.LoginViewModel"的定义.

No definition found for 'com.abhishek.mvvmdemo.onboarding.LoginViewModel' has been found.

@RunWith(AndroidJUnit4::class)
@LargeTest
class LoginActivityTest : KoinTest {
    private lateinit var loginViewModel: LoginViewModel

    @get:Rule
    val activityRule = ActivityTestRule(LoginActivity::class.java)

    @Before
    fun beforeTest() {
        loginViewModel = declareMock()
        loadKoinModules(
            module {
//                single { ApiModule.providesApiService() }
                viewModel { loginViewModel }
            }
        )
    }

    @Test
    fun testProgress() {
        activityRule.launchActivity(null)
        onView(withId(R.id.emailEt))
            .perform(ViewActions.typeText("abhishek"))
    }

    @After
    fun afterTest() {
        stopKoin()
    }
}

我尝试了很多排列和组合,但是没有运气.我的gradle中也碰巧有以下配置

I have tried a lot of permutation and combinations but got no luck. I also happen to have following configuration in my gradle


testOptions {
        animationsDisabled = true
    }

    packagingOptions {
        pickFirst 'mockito-extensions/org.mockito.plugins.MockMaker'
    }

testInstrumentationRunner "com.abhishek.mvvmdemo.MyTestRunner"

TL; DR

这是一个 github示例,它再现了问题

推荐答案

这里发生的是 ActivityTestRule 在您的 @Before 方法之前启动了活动,因此进行了模拟没有机会初始化.

What's happening here is that the ActivityTestRule launches the activity before your @Before method, so the mock has no chance to be initialized.

从官方文档

此规则提供单个活动的功能测试.什么时候在构造函数中将launchActivity设置为true,在测试将在每个用Test注释的测试之前和之前启动用Before注释的方法,它将在测试完成,并用After注释的方法已完成.

This rule provides functional testing of a single Activity. When launchActivity is set to true in the constructor, the Activity under test will be launched before each test annotated with Test and before methods annotated with Before, and it will be terminated after the test is completed and methods annotated with After are finished.

您应该使用此然后在测试方法中,您可以通过以下方式手动启动活动

Then in your test method you can launch your activity manually by

activityRule.launchActivity(null)

此外,您可能想查看 https://mockk.io/进行嘲笑.您不必将类声明为 open .

Also, you may want to check out https://mockk.io/ for mocking. You will not have to declare your classes as open.

这篇关于带有Mock ViewModel的NoBeanDefFoundException,使用Koin,Espresso进行测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆