web-dev-qa-db-ja.com

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.

ここに私のモジュール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'
}

そして、ここに私のテストの構造があります:

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
    }

私は何を間違えていますか?

31
J. Nuutinen

テストクラスから@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....
    }
}

このJavaテストは、Delegate runner for AndroidJunit4 could not be loadedエラーで失敗します。しかし、@RunWith注釈を削除すると、機能します。また、次のように@BeforeClassセットアップを@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....
    }
}

テストはエラーなしで実行されます。 @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...
    }

}

また、 Alessandro Biessek が回答で、@ Ioane Sharvadzeがコメントで言ったように、@Ruleアノテーションでも同じエラーが発生する可能性があります。行を追加する場合

 @Rule val instantTaskExecutorRule = InstantTaskExecutorRule()

Kotlinの例では、同じデリゲートランナーエラーが発生します。これは

@get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule()

説明 ここ

30
J. Nuutinen

また、Kotlinでテストルールを使用してJavaスタイルで記述すると、エラーメッセージが表示されます

@Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.Java)

@Rule@get:Ruleに変更する必要があります

@get:Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.Java) 
25
luckyhandler

@Testメソッドを削除すると、エラーメッセージが表示されます。

あなたは@Testメソッドを入れて実行しようとすることができます

@Test
public void signInTest() {


}
3
JackWu

変化

@Test
void someTest() {
    // Testing here
}

@Test
public void someTest() {
    // Testing here
}

私のために働く。

2
zwlxt

以下の依存関係を追加した後:

testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.Android.support.test:runner:1.0.1'
androidTestImplementation 
           'com.Android.support.test.espresso:espresso-core:3.0.1'

そして

Android{
defaultConfig{
    ...
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    ...
   }
}

AndroidJUnit4パッケージに属するクラスではなく、androidx.test.runnerパッケージに属する非推奨のandroidx.test.ext.junit.runners.AndroidJUnit4クラスを使用することは役に立ちません。

私はまだAndroidJUnit4クラスが廃止される理由を理解していませんが、それが属するGradle依存関係はAndroidチームによってすべての場所、つまり Codelabs および docs

1
neer17

@JvmFieldを使用できます。ドキュメントから

このプロパティのゲッター/セッターを生成せず、フィールドとして公開するようにKotlinコンパイラーに指示します

@Rule
@JvmField
val activityActivityTestRule = ActivityScenarioRule<MainActivity>(MainActivity::class.Java)

その他の考えられる理由:

  • @SmallTest(またはMedium-/Large-)テストメソッドのみがあります。少なくとも1つのメソッドを@Testでマークすると、問題が解決します。
  • setup()/teardown()メソッドはパブリックではありません。
0
WindRider

私にとって問題は@Ruleアノテーションでした。
今のところ原因はわかりません。

一時的な回避策として、たとえば、ActivityTestRuleのUIAutomatorを使用してアクティビティを開始できます。

0

おそらく、gradle configファイルのランナーを更新していないのでしょうか?

defaultConfig {
    ...
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

また、AndroidStudio 3.2には、依存関係のAndroidXへの移行を自動化するオプションがあります(リファクタリング-> AndroidXへの移行...)。

0
davisjp

私はこの構成で修正しました:

私の依存関係:

/*Instrumentation Test*/
androidTestImplementation "org.assertj:assertj-core:3.12.2"
androidTestImplementation ('androidx.test.espresso:espresso-core:3.2.0',{
    exclude group: 'com.Android.support', module: 'support-annotations'
})
androidTestImplementation "androidx.Arch.core:core-testing:2.1.0-rc01"

defaultConfigセクションには次のものがあります。

defaultConfig {
    applicationId "uy.edu.ude.archcomponents"
    minSdkVersion 22
    targetSdkVersion 28
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

    testInstrumentationRunnerArguments clearPackageData: 'true'
}

私が持っているテストでは:

package uy.edu.ude.archcomponents.repository

import androidx.Arch.core.executor.testing.InstantTaskExecutorRule
import androidx.room.Room
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import com.example.Android.roomwordssample.WordDao
import com.example.Android.roomwordssample.WordRoomDatabase
import kotlinx.coroutines.runBlocking
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import uy.edu.ude.archcomponents.entity.Word
import Java.io.IOException


@RunWith(AndroidJUnit4::class)
class WordDaoTest {

    @get:Rule
    val instantTaskExecutorRule = InstantTaskExecutorRule()

    private lateinit var wordDao: WordDao
    private lateinit var db: WordRoomDatabase

    @Before
    fun createDb() {
        val context = InstrumentationRegistry.getInstrumentation().context
        // Using an in-memory database because the information stored here disappears when the
        // process is killed.
        db = Room.inMemoryDatabaseBuilder(context, WordRoomDatabase::class.Java)
                // Allowing main thread queries, just for testing.
                .allowMainThreadQueries()
                .build()
        wordDao = db.wordDao()
    }

    @After
    @Throws(IOException::class)
    fun closeDb() {
        db.close()
    }

    @Test
    @Throws(Exception::class)
    fun insertAndGetWord() {
        runBlocking {
            val Word = Word("Word")
            wordDao.insert(Word)
            val allWords = wordDao.getAlphabetizedWords().waitForValue()
            assertThat(allWords[0].Word).isEqualTo(Word.word)
        }
    }
}

Androidプラグインバージョン3.4.2も使用します。 here から設定を取得しました

0
SHoko

単純にfunをprivateに設定するだけでこのエラーが発生しますが、これを削除すると解決しました。

0
Jesus Dimrix