हिल्ट टेस्टिंग गाइड

Hilt जैसे डिपेंडेंसी इंजेक्शन फ़्रेमवर्क का इस्तेमाल करने का एक फ़ायदा यह है कि इससे आपके कोड की जांच करना आसान हो जाता है.

यूनिट टेस्ट

यूनिट टेस्ट के लिए हिल्ट करना ज़रूरी नहीं है, क्योंकि ऐसी क्लास का टेस्ट करते समय जो कंस्ट्रक्टर इंजेक्शन के दौरान, आपको उस क्लास को इंस्टैंशिएट करने के लिए Hilt का इस्तेमाल करने की ज़रूरत नहीं है. इसके बजाय, आप नकली या मॉक पास करके सीधे क्लास कंस्ट्रक्टर को कॉल कर सकते है डिपेंडेंसी, जैसा कि कंस्ट्रक्टर के एनोटेट न होने पर किया जाता:

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(...);
  }
}

शुरू से अंत तक के टेस्ट

इंटिग्रेशन टेस्ट के लिए Hilt, डिपेंडेंसी इंजेक्ट करता है, जैसा कि यह आपके प्रोडक्शन में करता है कोड. Hilt के साथ परीक्षण करने के लिए किसी रखरखाव की ज़रूरत नहीं है, क्योंकि Hilt अपने आप होता है हर टेस्ट के लिए कॉम्पोनेंट का एक नया सेट जनरेट करता है.

टेस्टिंग डिपेंडेंसी जोड़ना

अपने टेस्ट में Hilt का इस्तेमाल करने के लिए, hilt-android-testing डिपेंडेंसी को अपने टेस्ट में शामिल करें प्रोजेक्ट:

ग्रूवी

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


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

Kotlin

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


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

यूज़र इंटरफ़ेस (यूआई) की जांच करने के लिए सेटअप

आपको ऐसे किसी भी यूज़र इंटरफ़ेस (यूआई) टेस्ट के बारे में जानकारी देनी होगी जिसमें @HiltAndroidTest के साथ Hilt का इस्तेमाल किया गया है. यह एनोटेशन की मदद से, हर टेस्ट के लिए Hilt के कॉम्पोनेंट जनरेट किए जाते हैं.

साथ ही, आपको टेस्ट क्लास में HiltAndroidRule जोड़ना होगा. यह कॉम्पोनेंट' इस स्थिति में टेस्ट के दौरान इंजेक्शन के लिए इस्तेमाल किया जाता है:

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.
}

इसके बाद, आपके टेस्ट को Hilt की उस Application क्लास के बारे में जानकारी होनी चाहिए आपके लिए अपने-आप जनरेट होता है.

ऐप्लिकेशन की जांच करें

आपको इंस्ट्रुमेंट किए गए ऐसे टेस्ट करने होंगे जो किसी Application ऑब्जेक्ट में Hilt का इस्तेमाल करते हैं जो Hilt के साथ काम करती है. टेस्ट में इस्तेमाल करने के लिए, लाइब्रेरी में HiltTestApplication की सुविधा उपलब्ध है. अगर आपके टेस्ट के लिए किसी दूसरे बेस ऐप्लिकेशन की ज़रूरत है, तो इसके लिए कस्टम ऐप्लिकेशन देखें टेस्ट.

आपको अपने instrumented में चलने के लिए अपना टेस्ट ऐप्लिकेशन सेट करना होगा परीक्षण या Robolectric टेस्ट किए जा सकते हैं. नीचे दिए गए निर्देशों को खास तौर पर Hilt के लिए है. हालांकि, इनमें सामान्य दिशा-निर्देश शामिल किए गए हैं कि में दिया जा सकता है.

इंस्ट्रुमेंट्ड टेस्ट में टेस्ट ऐप्लिकेशन सेट करें

इंस्ट्रुमेंट्ड में Hilt टेस्ट ऐप्लिकेशन का इस्तेमाल करने के लिए टेस्ट, आपको एक नया टेस्ट रनर कॉन्फ़िगर करना होगा. इससे Hilt आपके प्रोजेक्ट में मौजूद सभी इंस्ट्रुमेंटेड टेस्ट के लिए काम करता है. परफ़ॉर्म करें यहां बताया गया तरीका अपनाएं:

  1. ऐसी कस्टम क्लास बनाएं जो बड़ी हो AndroidJUnitRunner इंच androidTest फ़ोल्डर.
  2. newApplication फ़ंक्शन को बदलें और जनरेट किए गए नाम के लिए पास करें हिट टेस्ट ऐप्लिकेशन.

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);
  }
}

इसके बाद, इस टेस्ट रनर को अपनी Gradle फ़ाइल में कॉन्फ़िगर करें, जैसा कि इंस्ट्रूमेंटेड यूनिट टेस्ट गाइड देखें. पक्का करें कि आप पूरे क्लासपाथ का इस्तेमाल करते हैं:

ग्रूवी

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 टेस्ट में टेस्ट ऐप्लिकेशन सेट करें

अगर Robolectric का इस्तेमाल आपके यूज़र इंटरफ़ेस (यूआई) लेयर की जांच करने के लिए किया जाता है, तो यह तय किया जा सकता है कि कौनसा ऐप्लिकेशन robolectric.properties फ़ाइल में इस्तेमाल करने के लिए:

application = dagger.hilt.android.testing.HiltTestApplication

इसके अलावा, हर टेस्ट के लिए अलग-अलग ऐप्लिकेशन को कॉन्फ़िगर किया जा सकता है Robolectric @Config एनोटेशन का इस्तेमाल करके:

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 प्लग इन' के 4.2 से पहले वाले वर्शन का इस्तेमाल किया जा रहा है, तो स्थानीय यूनिट टेस्ट में @AndroidEntryPoint क्लास को पूरी तरह बदलना आपके मॉड्यूल की build.gradle फ़ाइल में नीचे दिया गया कॉन्फ़िगरेशन:

ग्रूवी

hilt {
    enableTransformForLocalTests = true
}

Kotlin

hilt {
    enableTransformForLocalTests = true
}

हिट में enableTransformForLocalTests के बारे में ज़्यादा जानकारी दस्तावेज़.

सुविधाएं टेस्ट करना

जब Hilt आपके परीक्षणों में इस्तेमाल के लिए तैयार हो जाए, तो आप इन कामों के लिए कई सुविधाओं का इस्तेमाल कर सकते हैं टेस्टिंग प्रोसेस को अपनी ज़रूरत के मुताबिक बनाने के लिए किया जा सकता है.

टेस्ट में टाइप इंजेक्ट करें

टेस्ट में टाइप इंजेक्ट करने के लिए, फ़ील्ड इंजेक्शन के लिए @Inject का इस्तेमाल करें. Hilt को यह बताने के लिए कि @Inject फ़ील्ड को भरने के लिए, hiltRule.inject() को कॉल करें.

इंस्ट्रुमेंटेड टेस्ट का यह उदाहरण देखें:

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.
  }
}

बाइंडिंग बदलना

अगर आपको किसी डिपेंडेंसी का कोई नकली या मॉक इंस्टेंस इंजेक्ट करना है, तो आपको बताना होगा उस बाइंडिंग का इस्तेमाल न करें जिसका इस्तेमाल उसने प्रोडक्शन कोड में किया है. साथ ही, नहीं करना है. बाइंडिंग को बदलने के लिए, आपको वह मॉड्यूल बदलना होगा इसमें एक टेस्ट मॉड्यूल के साथ बाइंडिंग है, जिसमें आपकी पसंद की बाइंडिंग हैं इस टूल का इस्तेमाल टेस्ट में किया जा सकता है.

उदाहरण के लिए, मान लें कि आपका प्रोडक्शन कोड AnalyticsService इस तरह से है:

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
  );
}

टेस्ट में AnalyticsService बाइंडिंग को बदलने के लिए, test या androidTest फ़ोल्डर में, नकली डिपेंडेंसी है और उस पर एनोटेट किया गया है @TestInstallIn के साथ. उस फ़ोल्डर में मौजूद सभी जांचों में नकली निर्भर नहीं करता है.

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
  );
}

एक टेस्ट में बाइंडिंग को बदलना

सभी टेस्ट के बजाय, एक ही टेस्ट में बाइंडिंग को बदलने के लिए, Hilt को अनइंस्टॉल करें @UninstallModules एनोटेशन का इस्तेमाल करके, टेस्ट से मॉड्यूल जोड़ें और नया मॉड्यूल बनाएं परीक्षण मॉड्यूल की जांच करें.

पिछले वर्शन में दिए गए AnalyticsService उदाहरण के मुताबिक आगे बढ़ते हुए, @UninstallModules एनोटेशन का इस्तेमाल करके, प्रोडक्शन मॉड्यूल को अनदेखा करने के लिए उसे घुमाएं टेस्ट क्लास में:

Kotlin

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

Java

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

इसके बाद, आपको बाइंडिंग बदलना होगा. टेस्ट क्लास में एक नया मॉड्यूल बनाएं टेस्ट बाइंडिंग के बारे में बताता है:

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
    );
  }
  ...
}

यह सिर्फ़ सिंगल टेस्ट क्लास की बाइंडिंग को बदलता है. अगर आपको अपनी रिपोर्ट में सभी टेस्ट क्लास के लिए बाइंडिंग, तो@TestInstallIn सेक्शन पढ़ें. इसके अलावा, टेस्ट बाइंडिंग को test मॉड्यूल में रखा जा सकता है या androidTest मॉड्यूल में इंस्ट्रुमेंटेड टेस्ट के लिए. हमारा सुझाव है कि जब भी मुमकिन हो, @TestInstallIn का इस्तेमाल करें.

नई वैल्यू बाइंड करना

अपने टेस्ट के फ़ील्ड को Hilt के साथ आसानी से बाइंड करने के लिए, @BindValue एनोटेशन का इस्तेमाल करें डिपेंडेंसी ग्राफ़. @BindValue के साथ फ़ील्ड के बारे में एनोटेट करें और वह इससे सीमित होगी तय किए गए फ़ील्ड टाइप के साथ-साथ, उस फ़ील्ड के लिए मौजूद किसी भी क्वालीफ़ायर के साथ.

AnalyticsService के उदाहरण में, AnalyticsService को इस तरह से बदला जा सकता है: @BindValue का इस्तेमाल करके नकली बनाया गया है:

Kotlin

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

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

  ...
}

Java

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

  @BindValue AnalyticsService analyticsService = FakeAnalyticsService();

  ...
}

यह आपके टेस्ट में बाइंडिंग को बदलने और बाइंडिंग का रेफ़रंस देने, दोनों को आसान बनाता है इससे आपको एक साथ दोनों काम करने की सुविधा मिलेगी.

@BindValue, क्वालीफ़ायर और दूसरे टेस्टिंग एनोटेशन के साथ काम करता है. उदाहरण के लिए, का इस्तेमाल किया जा सकता है, तो Mockito, तो आप इसका इस्तेमाल रोबोलेक्टिक टेस्ट इस तरह से:

Kotlin

...
class SettingsActivityTest {
  ...

  @BindValue @ExampleQualifier @Mock
  lateinit var qualifiedVariable: ExampleCustomType

  // Robolectric tests here
}

Java

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

  // Robolectric tests here
}

अगर आपको मल्टीबाइंडिंग जोड़ना है, तो आपके पास @BindValueIntoSet और @BindValueIntoMap एनोटेशन का इस्तेमाल करने का विकल्प है @BindValue में से. @BindValueIntoMap के लिए ज़रूरी है कि आप फ़ील्ड के बारे में व्याख्या करें शामिल किया जा सकता है.

विशेष मामले

Hilt में ऐसी सुविधाएं मौजूद हैं जिनकी मदद से, स्टैंडर्ड टूल का इस्तेमाल नहीं किया जा सकता.

जांच के लिए पसंद के मुताबिक ऐप्लिकेशन

अगर आप HiltTestApplication का इस्तेमाल नहीं कर पा रहे हैं, क्योंकि आपके टेस्ट ऐप्लिकेशन को ये काम करने होंगे किसी अन्य ऐप्लिकेशन का विस्तार करें, उसकी @CustomTestApplication, जिस बेस क्लास की वैल्यू पास करनी है उसे बढ़ाने के लिए Hilt ऐप्लिकेशन जनरेट किया गया.

@CustomTestApplication ऐसी Application क्लास जनरेट करेगा जो जांच के लिए तैयार है Hilt के साथ मौजूद है. यह पैरामीटर के तौर पर पास किए गए ऐप्लिकेशन को आगे बढ़ाता है.

Kotlin

@CustomTestApplication(BaseApplication::class)
interface HiltTestApplication

Java

@CustomTestApplication(BaseApplication.class)
interface HiltTestApplication { }

इस उदाहरण में, Hilt एक Application जनरेट करता है. HiltTestApplication_Application जो BaseApplication क्लास को बढ़ाता है. तय सीमा में आम तौर पर, जनरेट किए गए ऐप्लिकेशन का नाम ही एनोटेशन होता है. क्लास को _Application से जोड़ा गया. आपको जनरेट किया गया Hilt टेस्ट सेट करना होगा इंस्ट्रुमेंट वाले टेस्ट में चलाने के लिए ऐप्लिकेशन या Robolectric टेस्ट जैसा कि टेस्ट में बताया गया है आवेदन के बारे में ज़्यादा जानें.

आपके इंस्ट्रुमेंट किए गए टेस्ट में एक से ज़्यादा TestRule ऑब्जेक्ट

अगर आपके टेस्ट में अन्य TestRule ऑब्जेक्ट हैं, तो ऐसा करने के कई तरीके हैं पक्का करें कि सभी नियम एक साथ काम करें.

नियमों को इस तरह से एक साथ रखा जा सकता है:

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.
}

इसके अलावा, आप दोनों नियमों का एक ही स्तर पर तब तक उपयोग कर सकते हैं, जब तक HiltAndroidRule पहले लागू करता है. कार्यान्वयन का क्रम तय करने के लिए @Rule एनोटेशन में order एट्रिब्यूट. यह सिर्फ़ JUnit वर्शन में काम करता है 4.13 या इसके बाद के वर्शन:

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 का इस्तेमाल Hilt के साथ androidx.fragment:fragment-testing लाइब्रेरी, क्योंकि यह एक गतिविधि जो @AndroidEntryPoint के साथ एनोटेट नहीं की गई है.

इसका इस्तेमाल करें launchFragmentInHiltContainer कोड से architecture-samples GitHub डेटा स्टोर करने की जगह का इस्तेमाल करें.

सिंगलटन कॉम्पोनेंट उपलब्ध होने से पहले, एंट्री पॉइंट का इस्तेमाल करें

जब कोई हिल्ट एंट्री होती है, तो @EarlyEntryPoint एनोटेशन एक एस्केप हैच देता है में सिंगलटन कॉम्पोनेंट उपलब्ध होने से पहले पॉइंट बनाना ज़रूरी है हिल्ट टेस्ट.

@EarlyEntryPoint के बारे में ज़्यादा जानकारी के लिए, हिल्ट से जुड़ा दस्तावेज़.