Коин - как предоставить макет ViewModel для теста эспрессо? - PullRequest
0 голосов
/ 16 октября 2018

Как мы можем добавить макет viewModel в Activity для теста эспрессо?Используя 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")))
    }
}

1 Ответ

0 голосов
/ 16 октября 2018

В этом случае в тесте 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)))
    }
}

Пример кода

...