Hilt test kılavuzu

Hilt gibi bağımlılık yerleştirme çerçeveleri kullanmanın avantajlarından biri kodunuzu test etmeyi kolaylaştırır.

Birim testleri

oluşturucu enjeksiyonu varsa bu sınıfı örneklendirmek için Hilt'i kullanmanız gerekmez. Bunun yerine, sahte veya sahte dosya ileterek bir sınıf oluşturucuyu doğrudan çağırabilirsiniz. bağımlılıkları, kurucu için açıklama eklenmediğinde yapacağınız gibi:

Kotlin

@ActivityScoped
class AnalyticsAdapter @Inject constructor(
  private val service: AnalyticsService
) { ... }

class AnalyticsAdapterTest {

  @Test
  fun `Happy path`() {
    // You don't need Hilt to create an instance of AnalyticsAdapter.
    // You can pass a fake or mock AnalyticsService.
    val adapter = AnalyticsAdapter(fakeAnalyticsService)
    assertEquals(...)
  }
}

Java

@ActivityScope
public class AnalyticsAdapter {

  private final AnalyticsService analyticsService;

  @Inject
  AnalyticsAdapter(AnalyticsService analyticsService) {
    this.analyticsService = analyticsService;
  }
}

public final class AnalyticsAdapterTest {

  @Test
  public void happyPath() {
    // You don't need Hilt to create an instance of AnalyticsAdapter.
    // You can pass a fake or mock AnalyticsService.
    AnalyticsAdapter adapter = new AnalyticsAdapter(fakeAnalyticsService);
    assertEquals(...);
  }
}

Uçtan uca testler

Hilt, entegrasyon testleri için bağımlılıkları üretimde olduğu gibi ekler. girin. Hilt her test için otomatik olarak yeni bir bileşen grubu oluşturduğundan Hilt ile test yapmak için bakım gerekmez.

Test bağımlılıkları ekleme

Hilt'i testlerinizde kullanmak içinhilt-android-testing proje:

Eski

dependencies {
    // For Robolectric tests.
    testImplementation 'com.google.dagger:hilt-android-testing:2.51.1'
    // ...with Kotlin.
    kaptTest 'com.google.dagger:hilt-android-compiler:2.51.1'
    // ...with Java.
    testAnnotationProcessor 'com.google.dagger:hilt-android-compiler:2.51.1'


    // For instrumented tests.
    androidTestImplementation 'com.google.dagger:hilt-android-testing:2.51.1'
    // ...with Kotlin.
    kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.51.1'
    // ...with Java.
    androidTestAnnotationProcessor 'com.google.dagger:hilt-android-compiler:2.51.1'
}

Kotlin

dependencies {
    // For Robolectric tests.
    testImplementation("com.google.dagger:hilt-android-testing:2.51.1")
    // ...with Kotlin.
    kaptTest("com.google.dagger:hilt-android-compiler:2.51.1")
    // ...with Java.
    testAnnotationProcessor("com.google.dagger:hilt-android-compiler:2.51.1")


    // For instrumented tests.
    androidTestImplementation("com.google.dagger:hilt-android-testing:2.51.1")
    // ...with Kotlin.
    kaptAndroidTest("com.google.dagger:hilt-android-compiler:2.51.1")
    // ...with Java.
    androidTestAnnotationProcessor("com.google.dagger:hilt-android-compiler:2.51.1")
}

Kullanıcı arayüzü test kurulumu

Hilt'i kullanan tüm kullanıcı arayüzü testlerine @HiltAndroidTest ile açıklama eklemeniz gerekir. Bu ek açıklaması, her test için Hilt bileşenlerini oluşturmaktan sorumludur.

Ayrıca, HiltAndroidRule öğesini test sınıfına eklemeniz gerekir. bileşenler durumudur ve testinize ekleme işlemi gerçekleştirmek için kullanılır:

Kotlin

@HiltAndroidTest
class SettingsActivityTest {

  @get:Rule
  var hiltRule = HiltAndroidRule(this)

  // UI tests here.
}

Java

@HiltAndroidTest
public final class SettingsActivityTest {

  @Rule
  public HiltAndroidRule hiltRule = new HiltAndroidRule(this);

  // UI tests here.
}

Ardından, testinizin Hilt'in sizin için otomatik olarak oluşturduğu Application sınıfını bilmesi gerekir.

Test uygulaması

Hilt'i destekleyen bir Application nesnesinde Hilt kullanan enstrümante testler çalıştırmanız gerekir. Kitaplık, testlerde kullanılmak üzere HiltTestApplication sağlar. Testleriniz için farklı bir temel uygulamaya ihtiyaç duyuyorsanız Özel uygulama testlerinde bulabilirsiniz.

Test uygulamanızı, kullandığınız araçlar ile testler veya Robolectric testleriyle ilgili daha fazla bilgi edinin. Aşağıdaki talimatlarda ancak özel bir değerin nasıl belirtileceğine ilişkin genel yönergelerdir. testlerde çalıştırılacak bir uygulamadır.

Test uygulamasını araçlı testlerde ayarlama

Hilt test uygulamasını araçla test edilen testlerde kullanmak için yeni bir test çalıştırıcıyı yapılandırmanız gerekir. Bu sayede Hilt, projenizdeki tüm enstrümante testler için çalışır. Gerçekleştirme şu adımları uygulayın:

  1. Genişletilen özel bir sınıf oluşturun AndroidJUnitRunner inç androidTest klasörü.
  2. newApplication işlevini geçersiz kıl ve oluşturulan işlevin adını ilet Hilt test uygulaması.

Kotlin

// A custom runner to set up the instrumented application class for tests.
class CustomTestRunner : AndroidJUnitRunner() {

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

Java

// A custom runner to set up the instrumented application class for tests.
public final class CustomTestRunner extends AndroidJUnitRunner {

  @Override
  public Application newApplication(ClassLoader cl, String className, Context context)
      throws ClassNotFoundException, IllegalAccessException, InstantiationException {
    return super.newApplication(cl, HiltTestApplication.class.getName(), context);
  }
}

Ardından, bu test çalıştırıcısını Gradle dosyanızda araçlı birim testi rehberini inceleyin. Şunlardan emin olun: sınıf yolunun tamamını kullanırsınız:

Groovy

android {
    defaultConfig {
        // Replace com.example.android.dagger with your class path.
        testInstrumentationRunner "com.example.android.dagger.CustomTestRunner"
    }
}

Kotlin

android {
    defaultConfig {
        // Replace com.example.android.dagger with your class path.
        testInstrumentationRunner = "com.example.android.dagger.CustomTestRunner"
    }
}
Robolectric testlerinde test uygulamasını ayarlama

Kullanıcı arayüzü katmanınızı test etmek için Robolectric'i kullanırsanız hangi uygulamanın robolectric.properties dosyasında kullanılacak:

application = dagger.hilt.android.testing.HiltTestApplication

Alternatif olarak, aşağıdakileri yaparak uygulamayı her testte ayrı ayrı yapılandırabilirsiniz: Robolectric'in @Config ek açıklaması kullanılarak:

Kotlin

@HiltAndroidTest
@Config(application = HiltTestApplication::class)
class SettingsActivityTest {

  @get:Rule
  var hiltRule = HiltAndroidRule(this)

  // Robolectric tests here.
}

Java

@HiltAndroidTest
@Config(application = HiltTestApplication.class)
class SettingsActivityTest {

  @Rule public HiltAndroidRule hiltRule = new HiltAndroidRule(this);

  // Robolectric tests here.
}

Android Gradle eklentisi 4.2'den eski bir sürüm kullanıyorsanız şunu uygulayarak @AndroidEntryPoint sınıflarını yerel birim testlerinde dönüştürme: modülünüzün build.gradle dosyasında aşağıdaki yapılandırmayı uygulayın:

Groovy

hilt {
    enableTransformForLocalTests = true
}

Kotlin

hilt {
    enableTransformForLocalTests = true
}

enableTransformForLocalTests hakkında daha fazla bilgiyi Hilt belgeleri bölümünde bulabilirsiniz.

Test özellikleri

Hilt, testlerinizde kullanıma hazır olduğunda aşağıdakileri gerçekleştirmek için çeşitli özellikleri kullanabilirsiniz: test sürecini özelleştirebilirsiniz.

Testlere tür ekleme

Bir teste tür eklemek için alan ekleme için @Inject kullanın. Hilt'e @Inject alanlarını doldurmak için hiltRule.inject() yöntemini çağırın.

Aşağıdaki araçlı test örneğine bakın:

Kotlin

@HiltAndroidTest
class SettingsActivityTest {

  @get:Rule
  var hiltRule = HiltAndroidRule(this)

  @Inject
  lateinit var analyticsAdapter: AnalyticsAdapter

  @Before
  fun init() {
    hiltRule.inject()
  }

  @Test
  fun `happy path`() {
    // Can already use analyticsAdapter here.
  }
}

Java

@HiltAndroidTest
public final class SettingsActivityTest {

  @Rule public HiltAndroidRule hiltRule = new HiltAndroidRule(this);

  @Inject AnalyticsAdapter analyticsAdapter;

  @Before
  public void init() {
    hiltRule.inject();
  }

  @Test
  public void happyPath() {
    // Can already use analyticsAdapter here.
  }
}

Bağlamayı değiştirme

Bir bağımlılığın sahte veya taklit örneğini eklemeniz gerekiyorsa Hilt'e, üretim kodunda kullandığı bağlamayı kullanmamasını ve bunun yerine farklı bir bağlama kullanmasını söylemeniz gerekir. Bir bağlamayı değiştirmek için, tablodaki modülü Google Analytics 4'te, istediğiniz bağlamaları içeren bir test modülüne her zaman olması gerekir.

Örneğin, üretim kodunuzun AnalyticsService şöyle:

Kotlin

@Module
@InstallIn(SingletonComponent::class)
abstract class AnalyticsModule {

  @Singleton
  @Binds
  abstract fun bindAnalyticsService(
    analyticsServiceImpl: AnalyticsServiceImpl
  ): AnalyticsService
}

Java

@Module
@InstallIn(SingletonComponent.class)
public abstract class AnalyticsModule {

  @Singleton
  @Binds
  public abstract AnalyticsService bindAnalyticsService(
    AnalyticsServiceImpl analyticsServiceImpl
  );
}

Testlerdeki AnalyticsService bağlamasını değiştirmek için test veya androidTest klasöründe sahte bağımlılığı olan yeni bir Hilt modülü oluşturun ve @TestInstallIn ile ek açıklama ekleyin. Bu klasördeki tüm testlere bunun yerine sahte bağımlılık eklenir.

Kotlin

@Module
@TestInstallIn(
    components = [SingletonComponent::class],
    replaces = [AnalyticsModule::class]
)
abstract class FakeAnalyticsModule {

  @Singleton
  @Binds
  abstract fun bindAnalyticsService(
    fakeAnalyticsService: FakeAnalyticsService
  ): AnalyticsService
}

Java

@Module
@TestInstallIn(
    components = SingletonComponent.class,
    replaces = AnalyticsModule.class
)
public abstract class FakeAnalyticsModule {

  @Singleton
  @Binds
  public abstract AnalyticsService bindAnalyticsService(
    FakeAnalyticsService fakeAnalyticsService
  );
}

Tek bir testte bağlamayı değiştirme

Tüm testler yerine tek bir testte bir bağlamayı değiştirmek için Hilt'i kaldırın modülünü kullanarak @UninstallModules ek açıklamasını kullanarak bir testten yeni bir test modülünün bir parçası.

Önceki sürümdeki AnalyticsService örneğini takip ederek, test sınıfında @UninstallModules ek açıklamasını kullanarak Hilt'e üretim modülünü yoksaymasını söyleyerek başlayın:

Kotlin

@UninstallModules(AnalyticsModule::class)
@HiltAndroidTest
class SettingsActivityTest { ... }

Java

@UninstallModules(AnalyticsModule.class)
@HiltAndroidTest
public final class SettingsActivityTest { ... }

Ardından, cilt kapağını değiştirmeniz gerekir. Test sınıfında yeni bir modül oluşturma şu etiketi tanımlar:

Kotlin

@UninstallModules(AnalyticsModule::class)
@HiltAndroidTest
class SettingsActivityTest {

  @Module
  @InstallIn(SingletonComponent::class)
  abstract class TestModule {

    @Singleton
    @Binds
    abstract fun bindAnalyticsService(
      fakeAnalyticsService: FakeAnalyticsService
    ): AnalyticsService
  }

  ...
}

Java

@UninstallModules(AnalyticsModule.class)
@HiltAndroidTest
public final class SettingsActivityTest {

  @Module
  @InstallIn(SingletonComponent.class)
  public abstract class TestModule {

    @Singleton
    @Binds
    public abstract AnalyticsService bindAnalyticsService(
      FakeAnalyticsService fakeAnalyticsService
    );
  }
  ...
}

Bu işlem yalnızca tek bir test sınıfının bağlamasını değiştirir. Tüm test sınıflarının bağlamasını değiştirmek istiyorsanız yukarıdaki bölümdeki @TestInstallIn ek açıklamasını kullanın. Alternatif olarak, test bağlamasını test modülüne yerleştirebilirsiniz veya araçlı testler için androidTest modülünde kullanılabilir. Mümkün olduğunda @TestInstallIn kullanmanızı öneririz.

Yeni değerleri bağlama

Testinizdeki alanları Hilt bağımlılık grafiğine kolayca bağlamak için @BindValue ek açıklamasını kullanın. Bir alana @BindValue ile ek açıklama eklediğinizde, bu alan, belirtilen alan türünün altına, o alanda bulunan tüm niteliklerle birlikte bağlanır.

AnalyticsService örneğinde, AnalyticsService yerine bir @BindValue kullanarak sahte:

Kotlin

@UninstallModules(AnalyticsModule::class)
@HiltAndroidTest
class SettingsActivityTest {

  @BindValue @JvmField
  val analyticsService: AnalyticsService = FakeAnalyticsService()

  ...
}

Java

@UninstallModules(AnalyticsModule.class)
@HiltAndroidTest
class SettingsActivityTest {

  @BindValue AnalyticsService analyticsService = FakeAnalyticsService();

  ...
}

Bu, testinizde hem bir bağlamayı değiştirmeyi hem de bir bağlama referans vermeyi kolaylaştırır Böylece her ikisini de aynı anda yapabilirsiniz.

@BindValue, niteleyicilerle ve diğer test ek açıklamalarıyla çalışır. Örneğin, Mockito gibi test kitaplıklarını kullanıyorsanız bunları Robolectric testinde aşağıdaki gibi kullanabilirsiniz:

Kotlin

...
class SettingsActivityTest {
  ...

  @BindValue @ExampleQualifier @Mock
  lateinit var qualifiedVariable: ExampleCustomType

  // Robolectric tests here
}

Java

...
class SettingsActivityTest {
  ...
  @BindValue @ExampleQualifier @Mock ExampleCustomType qualifiedVariable;

  // Robolectric tests here
}

Bir çoklu bağlama eklemeniz gerekirse: yerinde @BindValueIntoSet ve @BindValueIntoMap ek açıklamalarını kullanabilirsiniz / @BindValue. @BindValueIntoMap, alana bir harita anahtarı ek açıklaması da eklemenizi gerektirir.

Özel durumlar

Hilt, standart dışı kullanım alanlarını destekleyecek özellikler de sunar.

Testler için özel uygulama

Test uygulamanızın şunu yapması gerektiği için HiltTestApplication ürününü kullanamıyorsanız başka bir uygulamayı genişletin, yeni sınıfa veya arayüze @CustomTestApplication: oluşturuldu.

@CustomTestApplication, test için hazır bir Application sınıfı oluşturacak , parametre olarak ilettiğiniz uygulamayı genişleten Hilt ile oluşturun.

Kotlin

@CustomTestApplication(BaseApplication::class)
interface HiltTestApplication

Java

@CustomTestApplication(BaseApplication.class)
interface HiltTestApplication { }

Örnekte, Hilt, adlı bir Application BaseApplication sınıfını genişleten HiltTestApplication_Application. İçinde oluşturulan uygulamanın adı, ek açıklama sınıf _Application eklendi. Oluşturulan Hilt test uygulamasını, Test uygulaması bölümünde açıklandığı gibi araçlarla testlerinizde veya Robolectric testlerinizde çalıştıracak şekilde ayarlamanız gerekir.

Araçla test edilen testinizde birden fazla TestRule nesnesi

Testinizde başka TestRule nesneleri de varsa aşağıdakileri yapmanın birden çok yolu vardır: tüm kuralların birlikte çalıştığından emin olmaktır.

Kuralları aşağıdaki gibi bir araya getirebilirsiniz:

Kotlin

@HiltAndroidTest
class SettingsActivityTest {

  @get:Rule
  var rule = RuleChain.outerRule(HiltAndroidRule(this)).
        around(SettingsActivityTestRule(...))

  // UI tests here.
}

Java

@HiltAndroidTest
public final class SettingsActivityTest {

  @Rule public RuleChain rule = RuleChain.outerRule(new HiltAndroidRule(this))
        .around(new SettingsActivityTestRule(...));

  // UI tests here.
}

Alternatif olarak, HiltAndroidRule önce çalıştırıldığı sürece her iki kuralı da aynı seviyede kullanabilirsiniz. Yürütme siparişini şunu kullanarak belirtin: @Rule ek açıklamasındaki order özelliği. Bu yalnızca JUnit sürümünde çalışır 4.13 veya sonraki sürümler:

Kotlin

@HiltAndroidTest
class SettingsActivityTest {

  @get:Rule(order = 0)
  var hiltRule = HiltAndroidRule(this)

  @get:Rule(order = 1)
  var settingsActivityTestRule = SettingsActivityTestRule(...)

  // UI tests here.
}

Java

@HiltAndroidTest
public final class SettingsActivityTest {

  @Rule(order = 0)
  public HiltAndroidRule hiltRule = new HiltAndroidRule(this);

  @Rule(order = 1)
  public SettingsActivityTestRule settingsActivityTestRule = new SettingsActivityTestRule(...);

  // UI tests here.
}

LaunchFragmentInContainer içi

Hilt, @AndroidEntryPoint ile ek açıklama eklenmemiş bir etkinliğe dayandığı için androidx.fragment:fragment-testing kitaplığındaki launchFragmentInContainer öğesini Hilt ile kullanmak mümkün değildir.

Şunu kullanın: launchFragmentInHiltContainer örneğinden architecture-samples GitHub depo olarak kullanabilirsiniz.

Singleton bileşeni kullanılabilir hale gelmeden önce bir giriş noktası kullanın

@EarlyEntryPoint ek açıklama, Hilt testinde tekil bileşen kullanılabilir hale gelmeden önce Hilt giriş noktası oluşturulması gerektiğinde bir kaçış yolu sağlar.

@EarlyEntryPoint hakkında daha fazla bilgi: Hilt belgeleri.