アプリを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
}
私は何を間違えていますか?
テストクラスから@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()
説明 ここ 。
また、Kotlinでテストルールを使用してJavaスタイルで記述すると、エラーメッセージが表示されます
@Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.Java)
@Rule
を@get:Rule
に変更する必要があります
@get:Rule
var mainActivityActivityTestRule = ActivityTestRule(MainActivity::class.Java)
@Testメソッドを削除すると、エラーメッセージが表示されます。
あなたは@Testメソッドを入れて実行しようとすることができます
@Test
public void signInTest() {
}
変化
@Test
void someTest() {
// Testing here
}
に
@Test
public void someTest() {
// Testing here
}
私のために働く。
以下の依存関係を追加した後:
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
@JvmField
を使用できます。ドキュメントから
このプロパティのゲッター/セッターを生成せず、フィールドとして公開するようにKotlinコンパイラーに指示します
@Rule
@JvmField
val activityActivityTestRule = ActivityScenarioRule<MainActivity>(MainActivity::class.Java)
その他の考えられる理由:
@SmallTest
(またはMedium-/Large-)テストメソッドのみがあります。少なくとも1つのメソッドを@Test
でマークすると、問題が解決します。setup()
/teardown()
メソッドはパブリックではありません。私にとって問題は@Rule
アノテーションでした。
今のところ原因はわかりません。
一時的な回避策として、たとえば、ActivityTestRuleのUIAutomatorを使用してアクティビティを開始できます。
おそらく、gradle configファイルのランナーを更新していないのでしょうか?
defaultConfig {
...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
また、AndroidStudio 3.2には、依存関係のAndroidXへの移行を自動化するオプションがあります(リファクタリング-> AndroidXへの移行...)。
私はこの構成で修正しました:
私の依存関係:
/*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 から設定を取得しました
単純にfunをprivateに設定するだけでこのエラーが発生しますが、これを削除すると解決しました。