[英]How can I add unit test for android architecture components life cycle event?
我嘗試為支持架構組件生命周期事件的 function 添加單元測試。 為了支持生命周期事件,我為我的 function 添加了@OnLifecycleEvent
注釋,我想在事件發生時做一些事情。
一切都按預期工作,但我想為 function 創建一個單元測試,以檢查我的 function 在預期事件發生時運行。
public class CarServiceProvider implements LifecycleObserver {
public void bindToLifeCycle(LifecycleOwner lifecycleOwner) {
lifecycleOwner.getLifecycle().addObserver(this);
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onClear() {
Log.i("CarServiceProvider", "onClear called");
}
}
我試圖模擬 LifecycleOwner 並創建新的 LifecycleRegistery 來更改生命周期觀察者的 state 但我沒有這樣做。
當 state 更改時,如何測試我的onClear()
function 調用?
您應該能夠使用LifecycleRegistry
您的測試將執行以下操作:
@Test
public void testSomething() {
LifecycleRegistry lifecycle = new LifecycleRegistry(mock(LifecycleOwner.class));
// Instantiate your class to test
CarServiceProvider carServiceProvider = new CarServiceProvider();
carServiceProvider.bindToLifeCycle(lifecycle);
// Set lifecycle state
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
// Verify that the ON_STOP event was handled, with an assert or similar check
...
}
如果您正在測試Lifecycle.Event.ON_DESTROY,那么您可能需要在此之前調用handleLifecycleEvent(Lifecycle.Event.ON_CREATE) 。
只要您正確模擬生命周期所有者,您就可以使用沒有 Roboletric 的單元測試進行測試。
val lifecycleOwner: LifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
val lifecycle = LifecycleRegistry(Mockito.mock(LifecycleOwner::class.java))
lifecycle.markState(Lifecycle.State.RESUMED)
Mockito.`when`(lifecycleOwner.lifecycle).thenReturn(lifecycle)
當您觀察變量時使用此生命周期所有者,您可以使用 Mockito.verify 查看您的回調是否已被調用
盡管我不是一個大粉絲,但我會和Robolectric 一起使用ActivityController來實現這一點。
鑒於在 Android Lifecycle 工作流中應用的Observer 模式的“Observables”是活動、片段......應用程序上下文是必須的,我們需要以某種方式將它帶到我們的測試場景中。
我通過這樣做達到了預期的結果
構建.gradle
testCompile "org.robolectric:robolectric:3.5.1"
CarServiceProviderTest.java
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class CarServiceProviderTest {
@Test
public void shouldFireOnClear(){
//Grab the Activity controller
ActivityController controller = Robolectric.buildActivity(JustTestActivity.class).create().start();
AppCompatActivity activity = (AppCompatActivity) controller.get();
//Instanciate our Observer
CarServiceProvider carServiceProvider = new CarServiceProvider();
carServiceProvider.bindToLifeCycle(activity);
//Fire the expected event
controller.stop();
//Assert
Assert.assertTrue(carServiceProvider.wasFired);
}
}
汽車服務提供者.java
public class CarServiceProvider implements LifecycleObserver {
public boolean wasFired;
public void bindToLifeCycle(LifecycleOwner lifecycleOwner) {
lifecycleOwner.getLifecycle().addObserver(this);
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onClear() {
wasFired = true;
}
}
擴展Raz's
答案,在 Kotlin 中,您可以創建一個擴展函數以使其更可重用。
fun LifecycleObserver.testLifeCycleEvent(lifecycleEvent: Lifecycle.Event) {
val mockLifeCycleOwner: LifecycleOwner = mockk()
val lifecycleRegistry = LifecycleRegistry(mockLifeCycleOwner)
lifecycleRegistry.addObserver(this)
lifecycleRegistry.handleLifecycleEvent(lifecycleEvent)
}
在最初的提問者的案例中,他們有一個fun bindToLifecycle()
。 如果您正在做類似的事情,您也可以為此創建一個擴展函數,以便它適用於所有LifecycleObserver
類型:
fun LifecycleObserver.bindToLifeCycle(lifecycle: Lifecycle) {
lifecycle.addObserver(this);
}
然后像這樣修改testLifeCycleEvent()
:
fun LifecycleObserver.testLifeCycleEvent(lifecycleEvent: Lifecycle.Event) {
val mockLifeCycleOwner: LifecycleOwner = mockk()
val lifecycleRegistry = LifecycleRegistry(mockLifeCycleOwner)
this.bindLifecycle(lifecycleRegistry)
lifecycleRegistry.handleLifecycleEvent(lifecycleEvent)
}
如果你想用真正的單元測試(不是 AndroidTest)來測試它,你最好的選擇是使用 Robolectric,它模擬了 Android 框架並且 Robolectric 4.0 即將推出。 但是,您正在嘗試測試與 Android 框架的實際交互,因此該任務更適合真正的集成測試套件和 AndroidTest。 您可以對其進行單元測試,但最可靠的測試方法是在設備上實際調用生命周期事件(Espresso 會做什么)並驗證它是否被調用。
Powermock v3.8 和 RESUME 事件有一個示例。 我使用此事件來展示如何驗證 livedata 值
#build.gradle
dependencies {
...
testImplementation 'org.robolectric:robolectric:3.8'
testImplementation "org.powermock:powermock-module-junit4:2.0.2"
testImplementation "org.powermock:powermock-module-junit4-rule:2.0.2"
testImplementation "org.powermock:powermock-api-mockito2:2.0.2"
testImplementation "org.powermock:powermock-classloading-xstream:1.6.4"
...
}
#CustomViewModel.kt
class CustomViewModel() : ViewModel(), LifecycleObserver {
private val _outputData = MutableLiveData<Boolean>()
val outputData: LiveData<Boolean> = _outputData
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume() {
//TODO action
outputData.value = true
}
}
#CustomViewModelTest.kt
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.mock
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.powermock.core.classloader.annotations.PowerMockIgnore
import org.powermock.modules.junit4.PowerMockRunner
import org.powermock.modules.junit4.PowerMockRunnerDelegate
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@RunWith(PowerMockRunner::class)
@PowerMockRunnerDelegate(RobolectricTestRunner::class)
@PowerMockIgnore("org.mockito.*", "org.robolectric.*", "androidx.*")
@Config(manifest = Config.NONE)
class CustomViewModelTest {
@Mock
lateinit var observer: Observer<in Boolean>
@Before
fun beforeTest() {
MockitoAnnotations.initMocks(this)
}
@Test
@Config(sdk = [Build.VERSION_CODES.O])
fun `do an action on resume event`() {
val vm = spy(CustomViewModel())
vm.outputData.observeForever(observer)
vm.testLifecycleEvent(Lifecycle.Event.ON_RESUME)
verify(vm).onResume()
verify(observer).onChange(true)
}
}
fun LifecycleObserver.testLifecycleEvent(lifecycleEvent: Lifecycle.Event) {
val lifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
val lifecycleRegistry = LifecycleRegistry(lifecycleOwner)
this.bindToLifecycle(lifecycleRegistry)
lifecycleRegistry.handleLifecycleEvent(lifecycleEvent)
}
fun LifecycleObserver.bindToLifecycle(lifecycle: Lifecycle) {
lifecycle.addObserver(this)
}
您可以使用 TestLifecycleOwner 從
androidx.lifecycle:lifecycle-runtime-testing
依賴
https://developer.android.com/reference/kotlin/androidx/lifecycle/testing/TestLifecycleOwner
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.