【问题标题】:MutableLiveData is null in JUnitTestJUnit 测试中的可变实时数据为空
【发布时间】:2018-04-15 09:30:55
【问题描述】:

我想写一个单元测试。因此我需要 MutableLiveData。我从一个非常基本的设置测试开始,但我无法实例化 MutableLiveData 对象。运行测试时,我总是为空。我必须嘲笑什么吗?有什么建议么?

@RunWith(MockitoJUnitRunner.class)
public class DefaultLiveDataTest {

    private static final int EXPECTED = 5;

    private final MutableLiveData<Integer> underTest = new MutableLiveData<>();


    @Test
    public void exampleTest() {

    underTest.setValue(EXPECTED); //underTest is Null
    assertEquals(underTest.getValue().intValue(), EXPECTED);

    }
}

java.lang.NullPointerException
at android.arch.core.executor.DefaultTaskExecutor.isMainThread(DefaultTaskExecutor.java:58)
at android.arch.core.executor.ArchTaskExecutor.isMainThread(ArchTaskExecutor.java:116)
at android.arch.lifecycle.LiveData.assertMainThread(LiveData.java:434)
at android.arch.lifecycle.LiveData.setValue(LiveData.java:279)
at android.arch.lifecycle.MutableLiveData.setValue(MutableLiveData.java:33)
at com.mypackage.DefaultLiveDataTest.test_that_live_data_has_default_value(DefaultLiveDataTest.java:22)

build.gradle

apply plugin: 'com.android.application'

android {
compileSdkVersion 27
defaultConfig {
    applicationId 'com.mypackage.title'
    minSdkVersion 16
    targetSdkVersion 27
    versionCode 1
    versionName '1.0'
    testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
}

testOptions {
    unitTests.returnDefaultValues = true
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.android.support:support-vector-drawable:27.1.1'
implementation 'android.arch.lifecycle:extensions:1.1.1'
implementation 'android.arch.lifecycle:viewmodel:1.1.1'
implementation 'android.arch.lifecycle:livedata:1.1.1'

annotationProcessor 'android.arch.lifecycle:compiler:1.1.1'
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:1.10.19'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
annotationProcessor 'org.androidannotations:androidannotations:4.4.0'
implementation 'org.androidannotations:androidannotations-api:4.4.0'
compileOnly 'org.projectlombok:lombok:1.16.20'
annotationProcessor 'org.projectlombok:lombok:1.16.20'
}

【问题讨论】:

    标签: android testing androidx android-testing android-livedata


    【解决方案1】:

    看起来您缺少 android.arch.core:core-testing 依赖项。

    testImplementation "android.arch.core:core-testing:1.1.1"
    

    这允许您在测试中使用 InstantTaskExecutorRule,这将摆脱 isMainThread 调用。

    https://developer.android.com/reference/android/arch/core/executor/testing/InstantTaskExecutorRule.html

    @Rule
    public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
    

    【讨论】:

    • 请注意,如果您仍然使用 mockito 1.x,这将强制您更新到 mockito 2.19
    • 对于 androidx 会有什么依赖?
    • 对于 AndroidX,它目前是 androidx.arch.core:core-testing:2.1.0。另请注意,该规则似乎仅适用于 JUnit 4,但不适用于 5。
    • 是的,对于 Junit 5,您只需创建自己的扩展。如果它在 Stackoverflow 上还没有,那么请随意创建一个问题,我可以添加我的自定义扩展的实现。 @SoH 如果您在此处链接问题
    • @MichaelTroger 是我的问题的链接:stackoverflow.com/questions/61582063/…
    【解决方案2】:

    添加一个执行器InstantTaskExecutorRule()作为Test类的成员

    交换后台执行程序的 JUnit 测试规则 具有执行每个任务的不同组件的架构组件 同步。您可以将此规则用于使用 架构组件。

    //@RunWith(JUnit4::class)   // For JUnit4
    @ExtendWith(InstantExecutorExtension::class)   // For JUnit5
    class FilterViewModelTest {
    
        @Rule @JvmField
        val instantTaskExecutorRule = InstantTaskExecutorRule()
    
        @Test
        fun test() {
            //Here you don't ask if isMainThread
        }
    }
    

    build.gradle(:mobile)

    android {
        //...
        dependencies {
            //...
            testImplementation 'androidx.arch.core:core-testing:2.1.0'
            androidTestImplementation 'androidx.arch.core:core-testing:2.1.0'
        }
    }
    

    GL

    InstantTaskExecutorRule

    【讨论】:

    • 这是最新的答案。谢谢。
    • 我错过了@RunWith(JUnit4::class),互联网上没有任何其他答案提到这一点。谢谢你的朋友。
    • 对于 junit5,将类顶部的 @RunWith(JUnit4::class) 替换为 @ExtendWith(InstantExecutorExtension::class) 并删除 val。
    【解决方案3】:

    我遇到了这个错误并通过添加 InstantTaskExecutorRule 解决了它:

    private lateinit var contactProfileViewModel: ContactProfileViewModel
    
    private val getStatusesForContact: GetStatusesForContact = mockk(relaxed = true)
    private val getStory: GetUserLastStory = mockk(relaxed = true)
    private val successStatusesCaptor = slot<((List<StatusDomain>) -> Unit)>()
    private val successStoryCaptor = slot<((List<StoryDomain>) -> Unit)>()
    
    @get:Rule
    val rule: TestRule = InstantTaskExecutorRule()
    
    @Before
    fun setUp(){
        contactProfileViewModel = ContactProfileViewModel(getStatusesForContact, getStory)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-22
      • 1970-01-01
      • 2019-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多