将Junit4测试迁移到androidx:是什么导致"委托运行器无法加载"?

J. *_*nen 40 junit android junit4 androidx

我正在将我的应用程序迁移到androidx,我似乎无法让我的单元测试工作.我从Google的AndroidJunitRunnerSample中获取了示例,该示例已更新为使用新的androidx api.尝试运行测试时出现以下错误:

java.lang.Exception: Delegate runner 'androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner' for AndroidJUnit4 could not be loaded. Check your build configuration.
Run Code Online (Sandbox Code Playgroud)

这是我的模块build.gradle:

android {
    defaultConfig {
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
}
dependencies {
    // Test dependencies
    androidTestImplementation 'androidx.test:core:1.0.0-beta02'
    androidTestImplementation 'androidx.test.ext:junit:1.0.0-beta02'
    androidTestImplementation 'androidx.test:runner:1.1.0-beta02'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-beta02'
    androidTestImplementation "androidx.arch.core:core-testing:2.0.0"
    androidTestImplementation 'androidx.room:room-testing:2.1.0-alpha01'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-beta02'
    androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
}
Run Code Online (Sandbox Code Playgroud)

以下是我的测试结构:

import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;

import androidx.test.ext.junit.runners.AndroidJUnit4;

@RunWith(AndroidJUnit4.class)
public class EntityParcelTest {

    @BeforeClass
    public void createEntities() {
        // Setup...
    }

    @Test
    void someTest() {
        // Testing here
    }
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

J. *_*nen 42

@RunWith(AndroidJUnit4.class)从测试类中删除注释修复了问题,虽然我无法真正说明为什么或如何修复它.

编辑:好吧我做了一些测试.我将我的应用程序迁移到Kotlin,突然我注意到测试也开始与@RunWith注释一起使用了.这是我发现的:

import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;

import androidx.test.ext.junit.runners.AndroidJUnit4;

@RunWith(AndroidJUnit4.class) // <-- @RunWith + @BeforeClass = Error
public class AndroidXJunitTestJava {

    @BeforeClass
    public static void setup() {
        // Setting up once before all tests
    }

    @Test
    public void testing() {
        // Testing....
    }
}
Run Code Online (Sandbox Code Playgroud)

此java测试失败并显示Delegate runner for AndroidJunit4 could not be loaded错误.但如果我删除@RunWith注释,它的工作原理.另外,如果我用@BeforeClassa 替换设置@Before,如下所示:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import androidx.test.ext.junit.runners.AndroidJUnit4;

@RunWith(AndroidJUnit4.class) // <-- @RunWith + @Before = works?
public class AndroidXJunitTestJava {

    @Before
    public void setup() {
        // Setting up before every test
    }

    @Test
    public void testing() {
        // Testing....
    }
}
Run Code Online (Sandbox Code Playgroud)

测试将运行没有错误.我需要使用@BeforeClass注释,所以我只是删除了@RunWith.

但是现在我正在使用Kotlin,以下(应该等于第一个java示例)可以工作:

import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class AndroidXJunitTest {

    companion object {
        @BeforeClass fun setup() {
            // Setting up
        }
    }

    @Test
    fun testing() {
        // Testing...
    }

}
Run Code Online (Sandbox Code Playgroud)

另外,正如Alessandro Biessek在回答和@Ioane Sharvadze的评论中所说的那样,注释也会出现同样的错误@Rule.如果我添加一行

 @Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
Run Code Online (Sandbox Code Playgroud)

对于Kotlin示例,发生了相同的委托运行程序错误.必须替换为

@get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
Run Code Online (Sandbox Code Playgroud)

这里解释.

  • 对我来说问题是我使用`@ Rule`而不是'ActivityTestRule`的`@get:Rule`注释.如果您使用的是"Kotlin",它可能对您有所帮助. (6认同)

luc*_*ler 31

如果您在Kotlin中使用测试规则并将其编写为Java样式,也会收到错误消息

@Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.java)
Run Code Online (Sandbox Code Playgroud)

您必须更改@Rule@get:Rule

@get:Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.java) 
Run Code Online (Sandbox Code Playgroud)

  • 使用@get:您将此注释添加到为此字段(即方法)而不是字段本身创建的java getter (3认同)
  • 好点子。我更喜欢使用“@JvmField”而不是“@get:”注释前缀,因为它生成的字节码与 Java 使用最初提到的语法生成的字节码相同。我不会说这是个人偏好(因为它做了不同的事情),但到目前为止,它在数百次测试中都是防错的,我确实更喜欢它,因为我可以验证它是否有效。 (2认同)

avi*_*ash 7

在测试活动时确保 ActivityTestRule 变量是 public :

@Rule
public ActivityTestRule<YourActivity> activityTestRule = new ActivityTestRule<>(YourActivity.class); 
Run Code Online (Sandbox Code Playgroud)


Jac*_*kWu 5

删除@Test方法时显示的错误消息。

您可以尝试放置@Test方法并运行

@Test
public void signInTest() {


}
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以尝试通过两种方法解决此问题:

解决方案一:

构建 --> 清理项目。然后构建 --> 重建项目

解决方案2:

有 2 个包包含 AndroidJUnit4

  1. androidx.test.runner(已弃用)
  2. androidx.test.ext.junit.runners

确保你的 build.gradle (应用程序)有这一行

android {
    defaultConfig {
    ....
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    ....
    }
}
Run Code Online (Sandbox Code Playgroud)

@RunWith(AndroidJUnit4.class)并确保在测试类之前使用 (1) (已弃用)而不是 (2) (新的但尚未稳定) 。

  • 尽管遵循官方文档,我还是花了大约 2 个小时才最终设置了一个 AndroidJUnitTest。正如我的测试类中的这个答案所述,我更改了导入:使用:`import androidx.test.runner.AndroidJUnit4`(尽管已弃用)不要使用:`import androidx.test.ext.junit.runners.AndroidJUnit4`。不是完美的解决方案。但最好使用已弃用的类,而不是仅仅为了运行单个测试而浪费更多时间。感谢您的回答。 (2认同)