Java.lang.Exception: Пользовательский класс runner AndroidJUnit4 должен иметь открытый конструктор с сигнатурой AndroidJUnit4 (класс testClass)

gradle выглядит следующим образом:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"

    defaultConfig {
        applicationId "com.google.developer.taskmaker"
        minSdkVersion 19
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

configurations.all {
    resolutionStrategy {
        force 'com.android.support:support-annotations:25.2.0'
    }
}


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:25.2.0'
    compile 'com.android.support:recyclerview-v7:25.2.0'
    compile 'com.android.support:design:25.2.0'
    compile 'com.android.support:preference-v7:25.2.0'
    debugCompile 'im.dino:dbinspector:[email protected]'
    // Android JUnit Runner
    compile 'com.google.android.gms:play-services-appindexing:8.4.0'
    // Android runner and rules support

    // add this for intent mocking support
    androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'

    // add this for webview testing support
    androidTestCompile 'com.android.support.test.espresso:espresso-web:2.2.2'
    compile 'com.android.support.test:runner:0.5'
    compile 'com.android.support.test:rules:0.5'
    compile 'com.android.support.test.espresso:espresso-core:2.2.2'
}

Unit test case выглядит как

@RunWith(AndroidJUnit4.class)
public class TestClass {

    @Rule
    public ActivityTestRule<MainActivity> mActivityRule =
            new ActivityTestRule<>(MainActivity.class);

    @Test
    public void buttonClick(){
        onView(withId(R.id.fab)).perform(click()).check(matches(isDisplayed()));
    }

}

Сообщение об ошибке выглядит так:

java.lang.Exception: Custom runner class AndroidJUnit4 should have a public constructor with signature AndroidJUnit4(Class testClass)

    at org.junit.runners.model.InitializationError.<init>(InitializationError.java:38)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:111)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:101)
    at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:87)
    at com.intellij.junit4.JUnit46ClassesRequestBuilder.collectWrappedRunners(JUnit46ClassesRequestBuilder.java:90)
    at com.intellij.junit4.JUnit46ClassesRequestBuilder.getClassesRequest(JUnit46ClassesRequestBuilder.java:51)
    at com.intellij.junit4.JUnit4TestRunnerUtil.buildRequest(JUnit4TestRunnerUtil.java:91)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:95)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)


Process finished with exit code -1

Я уже проверял другие ответы, но не получал решение. Пожалуйста, расскажите, где все пойдет не так. При запуске этого кода я получаю сообщение об ошибке

Ответы

Ответ 1

Причина 1: размещение тестов в неправильной папке

Эта ошибка может быть реплицирована путем создания нового приложения с шаблоном по умолчанию в Android Studio и копирования автоматически сгенерированного ExampleInstrumentedTest из androidTest в папку test:

неправильное копирование инструментального теста в тестовую папку

Вот как выглядит ошибка:

ошибка OPs java.lang.Exception: пользовательский класс runner AndroidJUnit4 должен иметь открытый конструктор с сигнатурой AndroidJUnit4 (класс testClass)

Обратите внимание, что для репликации проблемы вам также придется неправильно добавлять зависимости на уровне модуля build.gradle:

зависимости в неправильном месте

Причина 2: неправильная конфигурация теста

Локальные модульные тесты и инструментальные тесты имеют разные конфигурации запуска. Если вы нажмете "Изменить конфигурации", как показано ниже:

тестовая конфигурация

Вы должны увидеть свои контрольные тесты в разделе Android Instrumented Tests, а ваши локальные модули тестируются под Android JUnit, как показано на рисунках ниже:

Для Android Instrumented Tests конфигурация должна выглядеть примерно так:

test config для Android Instrumented tests

Для Android JUnit:

тестовая конфигурация для тестов Android JUnit

Когда вы запустите тест, Android Studio создаст для вас конфигурацию прогона. Если конфигурация прогона находится в неправильной категории, убедитесь, что у вас есть папки test и androidTest, и вы можете удалить конфигурацию прогона из Edit configurations и снова запустить тест. Если вы правильно настроили, на этот раз Android Studio будет использовать правильный тип конфигурации запуска.

Объяснение

В Android есть два типа тестов:

  • Тестируемые тесты
  • Локальные тесты

Контрольные тесты

Тестируемые тесты - это тесты, которые предназначены для работы на эмуляторе телефона или . Это те тесты, где вам необходим доступ к полнофункциональной части библиотеки Android (например, реальный Context). Они должны находиться в папке androidTest, а зависимости для этих тестов (например, Espresso, com.android.support.test.rules:0.5) будут иметь префикс androidTestCompile в вашем build.gradle.

Вот пример инструментального теста:

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

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

import static org.junit.Assert.assertEquals;

/**
 * Instrumentation test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void useAppContext() throws Exception {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();

        assertEquals("com.gyaltsab.myapplication", appContext.getPackageName());
    }
}

Локальные тесты

Локальные тесты - это тесты, которые вы можете запустить в своей среде IDE. Обычно они не зависят от какой-либо части библиотеки Android, недоступной на стандартной JVM (например, они не будут зависеть от Context). Зависимости для них идут в testCompile части вашего build.gradle.

Вот пример unit test:

import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        assertEquals(4, 2 + 2);
    }
}

Обратите внимание, что тесты локального блока не нуждаются в аннотации @RunWith(AndroidJUnit4.class) в объявлении класса. Для более полного объяснения см. официальные документы.

Ответ 2

У меня была та же проблема. Я работаю в студии Android 2.3.1. Я проверил свои настройки запуска. В разделе Run- > Edit Configurations и обнаруженный тест, который я пытался запустить в качестве инструментального теста, был включен в категорию тестов Android JUnit, хотя я использовал его в каталоге androidTest в моем проекте. Я добавил Android Instrumented Test (нажмите кнопку "плюс" в углу) и установил, чтобы он указывал на тест, который я пытался запустить. Это исправило это для меня.

Ответ 3

Попробуйте переместить тестовый файл в папку androidTest.