提问者:小点点

在JUnit5/Jupiter测试用例中尝试剑柄注入时出现NullPointerException


我正在尝试使用剑柄注入注入JUnit5/Jupiter测试用例,但遇到空指针异常。使用JUnit4一切正常。

重现一个简单的测试用例就足够了。

我的项目gradle文件

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext.kotlin_version = '1.5.20-M1'
    ext.hilt_version = '2.35'

    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.2.1"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
        classpath("de.mannodermaus.gradle.plugins:android-junit5:1.7.1.1")
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
        jcenter() // Warning: this repository is going to shut down soon
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

我的模块gradle文件

plugins {
    id 'com.android.application'
    id("dagger.hilt.android.plugin")
    id("de.mannodermaus.android-junit5")
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "de.negosa.myhilttestingapplication"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "de.negosa.myhilttestingapplication.HiltTestRunner"
        // 2) Connect JUnit 5 to the runner
        testInstrumentationRunnerArgument("runnerBuilder", "de.mannodermaus.junit5.AndroidJUnit5Builder")
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.3.0'

    // Kotlin
    implementation "androidx.core:core-ktx:1.5.0"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    // Hilt
    implementation("com.google.dagger:hilt-android:$hilt_version")
    kapt("com.google.dagger:hilt-android-compiler:$hilt_version")

    //
    // Local Testing

    // (Required) Writing and executing Unit Tests on the JUnit Platform
    testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.1")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.1")

    // (Optional) If you also have JUnit 4-based tests
    testImplementation 'junit:junit:4.13.2'
    testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.7.1")

    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    //
    // Instrumented Testing
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    // hilt testing
    androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
    // ...with Kotlin.
    kaptAndroidTest "com.google.dagger:hilt-android-compiler:$hilt_version"
    // 4) Jupiter API & Test Runner, if you don't have it already
    androidTestImplementation("androidx.test:runner:1.3.0")
    androidTestImplementation("org.junit.jupiter:junit-jupiter-api:5.7.1")

    // 5) The instrumentation test companion libraries
    androidTestImplementation("de.mannodermaus.junit5:android-test-core:1.2.2")
    androidTestRuntimeOnly("de.mannodermaus.junit5:android-test-runner:1.2.2")

}
repositories {
    mavenCentral()
}

我的HiltTestRunner

package de.negosa.myhilttestingapplication

import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
import dagger.hilt.android.testing.HiltTestApplication

class HiltTestRunner : AndroidJUnitRunner() {

    override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
        return super.newApplication(cl, HiltTestApplication::class.java.name, context)
    }
}

和我的测试用例文件

package de.negosa.myhilttestingapplication

import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Rule

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test


@HiltAndroidTest
class HiltTestingTest {
    @get: Rule
    var hiltRule = HiltAndroidRule(this)
    
    @BeforeEach
    fun setup() {
        hiltRule.inject()
    }

    @Test
    fun simpleTest() {

    }
}

错误信息是

java.lang.NullPointerException
    at dagger.hilt.internal.Preconditions.checkNotNull(Preconditions.java:34)
    at dagger.hilt.android.internal.testing.TestApplicationComponentManager.inject(TestApplicationComponentManager.java:250)
    at dagger.hilt.android.internal.testing.MarkThatRulesRanRule.inject(MarkThatRulesRanRule.java:81)
    at dagger.hilt.android.testing.HiltAndroidRule.inject(HiltAndroidRule.java:49)
    at de.negosa.myhilttestingapplication.HiltTestingTest.setup(HiltTestingTest.kt:18)
    at java.lang.reflect.Method.invoke(Native Method)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptLifecycleMethod(TimeoutExtension.java:126)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptBeforeEachMethod(TimeoutExtension.java:76)
    at org.junit.jupiter.engine.descriptor.-$$Lambda$bFHzkK-Gyd2nGL9G6f3WT3eZ7lM.apply(Unknown Source:0)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.-$$Lambda$ExecutableInvoker$ReflectiveInterceptorCall$AfiRfaQW5MFAa8lovVwndaKa8l0.apply(Unknown Source:2)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.-$$Lambda$ExecutableInvoker$hmdF2IKSQSF2OJBv_amWUUg0sS8.apply(Unknown Source:6)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeMethodInExtensionContext(ClassBasedTestDescriptor.java:490)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$synthesizeBeforeEachMethodAdapter$19$ClassBasedTestDescriptor(ClassBasedTestDescriptor.java:475)
    at org.junit.jupiter.engine.descriptor.-$$Lambda$ClassBasedTestDescriptor$tNV5uTg6yzrSAyoR9_LyHRWjPVk.invokeBeforeEachMethod(Unknown Source:4)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeEachMethods$2$TestMethodTestDescriptor(TestMethodTestDescriptor.java:167)
    at org.junit.jupiter.engine.descriptor.-$$Lambda$TestMethodTestDescriptor$pK5fUoWT43xVHP3Wk-jdF7k0URU.invoke(Unknown Source:6)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeMethodsOrCallbacksUntilExceptionOccurs$5(TestMethodTestDescriptor.java:195)
    at org.junit.jupiter.engine.descriptor.-$$Lambda$TestMethodTestDescriptor$Y4hAX5bQnGBfYTu_BFBCUC1ErL0.execute(Unknown Source:6)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeMethodsOrCallbacksUntilExceptionOccurs(TestMethodTestDescriptor.java:195)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeEachMethods(TestMethodTestDescriptor.java:164)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:127)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5$NodeTestTask(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$NodeTestTask$oEtjVUBr1dzvAyO4rHrqPrrp8iU.execute(Unknown Source:2)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7$NodeTestTask(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$NodeTestTask$sIF-wJyqQcSlbWMGWi7dBYWbuCo.invoke(Unknown Source:2)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8$NodeTestTask(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$NodeTestTask$EAUqZA5CfD8zbN3AlxhbCoS66eU.execute(Unknown Source:2)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$04TgCUAyYTiSsbqaEl88v4bsMqI.accept(Unknown Source:2)
    at java.util.ArrayList.forEach(ArrayList.java:1262)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5$NodeTestTask(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$NodeTestTask$oEtjVUBr1dzvAyO4rHrqPrrp8iU.execute(Unknown Source:2)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7$NodeTestTask(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$NodeTestTask$sIF-wJyqQcSlbWMGWi7dBYWbuCo.invoke(Unknown Source:2)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8$NodeTestTask(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$NodeTestTask$EAUqZA5CfD8zbN3AlxhbCoS66eU.execute(Unknown Source:2)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$04TgCUAyYTiSsbqaEl88v4bsMqI.accept(Unknown Source:2)
    at java.util.ArrayList.forEach(ArrayList.java:1262)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5$NodeTestTask(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$NodeTestTask$oEtjVUBr1dzvAyO4rHrqPrrp8iU.execute(Unknown Source:2)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7$NodeTestTask(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$NodeTestTask$sIF-wJyqQcSlbWMGWi7dBYWbuCo.invoke(Unknown Source:2)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8$NodeTestTask(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.-$$Lambda$NodeTestTask$EAUqZA5CfD8zbN3AlxhbCoS66eU.execute(Unknown Source:2)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0$EngineExecutionOrchestrator(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.-$$Lambda$EngineExecutionOrchestrator$eWp5Nw-Kiu1gM4ryu2PhdSQR8rg.accept(Unknown Source:8)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:84)
    at de.mannodermaus.junit5.AndroidJUnit5.run(AndroidJUnit5.java:126)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
    at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:395)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2205)

在我看来,HiltAndroidLaw没有初始化,但我不知道为什么。

有人知道吗?


共1个答案

匿名用户

HiltAndroidLaw未初始化,因为@Law仅JUnit4支持,但您在此处使用的是JUnit5。如果Android支持像JUnit5这样的新框架,那就太好了,但这似乎不会很快发生。

所以你有几个选择,你可以:

  1. 像您已经成功完成的那样使用JUnit4。
  2. 或者您可以使用@ExententBy使JUnit5等效。这篇文章可能会有帮助?

我想我会推荐#1,这样您就不必维护自己的JUnit5扩展,但它可能比我想象的更容易。