9

我们如何将模拟的 viewModel 注入到 Activity 中进行 espresso 测试?使用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")))
    }
}
4

1 回答 1

14

在这种情况下,Espresso 测试仍在使用主应用程序类,该类声明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"
    }
}

在开始活动之前声明模拟方法很重要

@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)))
    }
}

示例代码

于 2018-10-16T17:42:27.263 回答