本篇延續 Day13 MVVM專案-2 Simple Fragment -1
今天會將昨天沒寫完的instrumented test完成
首先先去以下路徑新增manifest
projectname/app/src/debug/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ithome11.jetpackmvvmdemo">
<application>
<activity android:name=".FragmentTestActivity" />
</application>
</manifest>
接著要追加一個專門用來測試fragment的activity
projectname/app/src/debug/yourPackageNameInDebugManifest/FragmentTestActivity.kt
@RestrictTo(RestrictTo.Scope.TESTS)
class FragmentTestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val v = FrameLayout(this).apply {
id = R.id.container
layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT
, FrameLayout.LayoutParams.MATCH_PARENT)
}
setContentView(v)
}
inline fun <reified T: androidx.fragment.app.Fragment>replaceFragment(f: T, tag: String = T::class.java.name) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, f, tag)
.commit()
}
inline fun <reified T: androidx.fragment.app.Fragment>addFragment(f: T, tag: String = T::class.java.name) {
supportFragmentManager.beginTransaction()
.add(R.id.container, f, tag)
.commit()
}
}
接著是測試代碼
S02FragmentTest.kt
@RunWith(AndroidJUnit4::class)
class S02FragmentTest {
@get:Rule
val rule = object : ActivityTestRule<FragmentTestActivity>(FragmentTestActivity::class.java) {}
private fun justTrue() = true
@Before
fun setFragment() {
// given
val createVMFactory = {
object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T =
Stage02ViewModel(::justTrue).apply {
speedOfAnim.value = 10.0f
} as T
}
}
rule.activity.replaceFragment(Stage02Fragment.newInstance(createVMFactory))
}
@Test
fun score_should_increase_when_success() {
// when
Espresso.onView(withId(R.id.bt_try)).perform(ViewActions.click())
Espresso.onView(isRoot())
.perform(ViewAssertionsEx.waiting(1000)) // waiting to end animation
// then
val expected =
String.format(rule.activity.resources.getString(R.string.stage02_score_format), 1)
Espresso.onView(withId(R.id.tv_score)).check(matches(withText(expected)))
}
object ViewAssertionsEx {
@JvmStatic
fun waiting(milliSec: Long) = object : ViewAction {
override fun getDescription(): String = "waiting $milliSec milli seconds"
override fun getConstraints(): Matcher<View> = isDisplayed()
override fun perform(uiController: UiController, view: View) =
uiController.loopMainThreadForAtLeast(milliSec)
}
}
}
其中 createVMFactory 其實是把之前Stage02ViewModelFactory創建的Factory給替換掉了
class Stage02ViewModelFactory : ViewModelProvider.Factory {
private fun randomBooleanGenerator(): () -> Boolean {
val r = Random()
return { r.nextBoolean() }
}
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T = when (modelClass) {
Stage02ViewModel::class.java -> Stage02ViewModel(randomBooleanGenerator())
else -> throw IllegalArgumentException("$modelClass is not registered ViewModel")
} as T
}
生成Boolean從亂數替換成總是true
另外viewModel的動畫運行速度也被調快
speedOfAnim.value = 10.0f
最後附上今日代碼
https://github.com/mars1120/jetpackMvvmDemo/tree/mvvm-02-fragment