今天要來試試寫 Unit Test,針對 ViewModel 的邏輯驗證不管什麼 input 都要符合我想要的 output,以下如有解釋不清或是描述錯誤的地方還請大家多多指教:
Unit Test 又稱為單元測試,測試每一個最小函式是否能正常運行,某些情境下會讓我們難以測試,所以在開發時要避免以下幾點:
而測試的流程只要符合 3A 大致就可以執行了:
原先在專案建立時就已經幫我們配置好了 Junit,另外在這邊使用 mockk 來 mock 我們預期的結果
dependencies {
def mockk_version = "1.12.3"
testImplementation 'junit:junit:4.13.2'
testImplementation "io.mockk:mockk:${mockk_version}"
testImplementation "io.mockk:mockk-android:${mockk_version}"
testImplementation "androidx.arch.core:core-testing:2.1.0"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4"
}
也可看到有兩個資料夾,一個是給 UI test 一個是給 Unit Test
class MainViewModelTest {
private val isCardInsertedOb: Observer<Resource<Boolean>> = mockk(relaxed = true)
private val repository: Repository = mockk(relaxed = true)
private lateinit var viewModel: MainViewModel
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
@Before
fun setup() {
viewModel = MainViewModel(repository)
viewModel.isCardInserted.observeForever(isCardInsertedOb)
}
@Test
fun getCurrentForecast() = runTest {
val testDispatcher = UnconfinedTestDispatcher(testScheduler)
Dispatchers.setMain(testDispatcher)
try {
viewModel.getForecast("test")
verify { isCardInsertedOb.onChanged(any()) }
assertEquals(true, (viewModel.isCardInserted.value as Resource.Success).data)
} finally {
Dispatchers.resetMain()
}
}
}