简体   繁体   English

Koin-如何为咖啡测试提供模拟ViewModel?

[英]Koin - how to provide mock ViewModel for espresso test?

How can we inject mocked viewModel into Activity for espresso test? 我们如何将模拟的viewModel注入到Activity中以进行浓缩咖啡测试? Using declareMock I get mock object in Test class but Activity receives regular viewModel object. 使用declareMock我在Test类中获得了模拟对象,但Activity接收了常规的viewModel对象。

@RunWith(AndroidJUnit4::class)
class SomeActivityTest : KoinTest {
    @Rule
    @JvmField
    val rule = ActivityTestRule(SomeActivity::class.java, true, true)
    val viewModel: MyViewModel by inject()

    @Before
    fun setup() {
        declareMock<MyViewModel>(isFactory = true, binds = listOf(ViewModel::class))
    }

    @After
    fun cleanUp() {
        stopKoin()
    }

    @Test
    fun shouldHaveTextViewVisible() {
        `when`(viewModel.sayHello())
                .thenReturn("hello view-model")
        onView(withId(R.id.tv_homescreen_message))
                .check(matches(isDisplayed()))
        onView(withId(R.id.tv_homescreen_message))
                .check(matches(withText("hello view-model")))
    }
}

In this case, Espresso test were still using main application class which declares all koin module required for app. 在这种情况下,Espresso测试仍在使用主应用程序类,该类声明了应用程序所需的所有koin模块。

Starting koin without any modules, allows us to load only required modules during test. koin没有任何模块的情况下启动koin ,允许我们在测试期间仅加载所需的模块。

// application class for espresso tests
class TestApp : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin(this, emptyList())
    }
}

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

// app module build.gradle
android {
    defaultConfig {
        testInstrumentationRunner "com.package.TestAppJUnitRunner"
    }
}

It is important to declare mock method before starting activity 在开始活动之前声明模拟方法很重要

@RunWith(AndroidJUnit4::class)
class SomeActivityTest : KoinTest {
    @Rule
    @JvmField
    val rule = ActivityTestRule(SomeActivity::class.java, true, false)

    lateinit var mockVm: MyViewModel


    @Before
    fun setup() {
        mockVm = mock(MyViewModel::class.java)

        loadKoinModules(module {
            viewModel {
                mockVm
            }
        })
    }

    @After
    fun cleanUp() {
        stopKoin()
    }

    @Test
    fun shouldHaveTextViewWithMessage() {
        // 1. declare mock method
        val message = "hello view-model"
        Mockito.`when`(mockVm.sayHello())
                .thenReturn(message)

        // 2. start activity
        rule.launchActivity(null)


        // 3. test
        onView(withId(R.id.tv_message))
                .check(matches(isDisplayed()))

        onView(withId(R.id.tv_message))
                .check(matches(withText(message)))
    }
}

Sample code 样例代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM