Hilt जैसे डिपेंडेंसी इंजेक्शन फ़्रेमवर्क का इस्तेमाल करने का एक फ़ायदा यह है कि इससे आपके कोड की जांच करना आसान हो जाता है.
यूनिट टेस्ट
यूनिट टेस्ट के लिए 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
डिपेंडेंसी शामिल करें:
Groovy
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") }
यूज़र इंटरफ़ेस (यूआई) टेस्ट सेटअप करना
आपको @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. }
इसके बाद, आपके टेस्ट को उस Application
क्लास के बारे में पता होना चाहिए जिसे Hilt आपके लिए अपने-आप जनरेट करता है.
ऐप्लिकेशन की जांच करना
आपको ऐसे इंस्ट्रूमेंट किए गए टेस्ट चलाने होंगे जो Hilt की सुविधा वाले Application
ऑब्जेक्ट में Hilt का इस्तेमाल करते हैं. लाइब्रेरी, टेस्ट में इस्तेमाल करने के लिए HiltTestApplication
उपलब्ध कराती है.
अगर आपके टेस्ट के लिए किसी दूसरे बेस ऐप्लिकेशन की ज़रूरत है, तो टेस्ट के लिए कस्टम ऐप्लिकेशन देखें.
आपको अपने टेस्ट ऐप्लिकेशन को इंस्ट्रूमेंट किए गए जांच या Robolectric जांच में चलाने के लिए सेट करना होगा. यहां दिए गए निर्देश, Hilt के लिए खास तौर पर नहीं हैं. हालांकि, ये टेस्ट में चलाए जाने वाले कस्टम ऐप्लिकेशन के बारे में बताने के सामान्य दिशा-निर्देश हैं.
इंस्ट्रूमेंट किए गए टेस्ट में टेस्ट ऐप्लिकेशन सेट करना
इंस्ट्रूमेंट किए गए टेस्ट में Hilt टेस्ट ऐप्लिकेशन का इस्तेमाल करने के लिए, आपको एक नया टेस्ट रनर कॉन्फ़िगर करना होगा. इससे Hilt, आपके प्रोजेक्ट में मौजूद सभी इंस्ट्रूमेंट किए गए टेस्ट के लिए काम करता है. यह तरीका अपनाएं:
androidTest
फ़ोल्डर में,AndroidJUnitRunner
को एक्सटेंड करने वाली कस्टम क्लास बनाएं.newApplication
फ़ंक्शन को बदलें और जनरेट किए गए Hilt टेस्ट ऐप्लिकेशन का नाम डालें.
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 फ़ाइल में इस टेस्ट रनर को कॉन्फ़िगर करें, जैसा कि इंस्ट्रुमेंट की गई यूनिट टेस्ट की गाइड में बताया गया है. पक्का करें कि आपने पूरे क्लासपाथ का इस्तेमाल किया हो:
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 टेस्ट में टेस्ट ऐप्लिकेशन सेट करना
अगर यूज़र इंटरफ़ेस (यूआई) लेयर की जांच करने के लिए 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 से पहले के वर्शन का इस्तेमाल किया जा रहा है, तो अपने मॉड्यूल की build.gradle
फ़ाइल में यह कॉन्फ़िगरेशन लागू करके, लोकल यूनिट टेस्ट में @AndroidEntryPoint
क्लास को ट्रांसफ़ॉर्म करने की सुविधा चालू करें:
Groovy
hilt { enableTransformForLocalTests = true }
Kotlin
hilt { enableTransformForLocalTests = true }
enableTransformForLocalTests
के बारे में ज़्यादा जानकारी के लिए, Hilt के दस्तावेज़ देखें.
जांच करने की सुविधाएं
जब 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. } }
बाइंडिंग बदलना
अगर आपको किसी डिपेंडेंसी का फ़र्ज़ी या मॉक इंस्टेंस इंजेक्ट करना है, तो आपको Hilt को यह बताना होगा कि वह प्रोडक्शन कोड में इस्तेमाल की गई बाइंडिंग का इस्तेमाल न करे और इसके बजाय किसी दूसरी बाइंडिंग का इस्तेमाल करे. किसी बाइंडिंग को बदलने के लिए, आपको उस मॉड्यूल को बदलना होगा जिसमें बाइंडिंग मौजूद है. इसके लिए, आपको टेस्ट मॉड्यूल का इस्तेमाल करना होगा. इस मॉड्यूल में वे बाइंडिंग मौजूद होनी चाहिए जिनका आपको टेस्ट में इस्तेमाल करना है.
उदाहरण के लिए, मान लें कि आपके प्रोडक्शन कोड में 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
फ़ोल्डर में नकली डिपेंडेंसी वाला नया Hilt मॉड्यूल बनाएं और उस पर @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 ); }
किसी एक टेस्ट में बाइंडिंग बदलना
सभी टेस्ट के बजाय, किसी एक टेस्ट में बाइंडिंग को बदलने के लिए, @UninstallModules
एनोटेशन का इस्तेमाल करके, टेस्ट से Hilt मॉड्यूल को अनइंस्टॉल करें. इसके बाद, टेस्ट में नया टेस्ट मॉड्यूल बनाएं.
पिछले वर्शन के AnalyticsService
उदाहरण के आधार पर, सबसे पहले Hilt को टेस्ट क्लास में @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
एनोटेशन का इस्तेमाल करें. इसके अलावा, Robolectric टेस्ट के लिए test
मॉड्यूल में या इंस्ट्रूमेंट किए गए टेस्ट के लिए androidTest
मॉड्यूल में, टेस्ट बाइंडिंग डाली जा सकती है.
हमारा सुझाव है कि जब भी हो सके, @TestInstallIn
का इस्तेमाल करें.
नई वैल्यू बांधना
अपने टेस्ट में मौजूद फ़ील्ड को Hilt डिपेंडेंसी ग्राफ़ में आसानी से बांधने के लिए, @BindValue
एनोटेशन का इस्तेमाल करें. किसी फ़ील्ड को @BindValue
के साथ एनोटेट करें. इससे वह फ़ील्ड, एनोटेट किए गए फ़ील्ड टाइप के तहत, उस फ़ील्ड के लिए मौजूद सभी क्वालिफ़ायर के साथ बाउंड हो जाएगा.
AnalyticsService
के उदाहरण में, @BindValue
का इस्तेमाल करके AnalyticsService
को किसी फ़ेक वैल्यू से बदला जा सकता है:
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 जैसी टेस्टिंग लाइब्रेरी का इस्तेमाल किया जाता है, तो इसका इस्तेमाल Robolectric टेस्ट में इस तरह किया जा सकता है:
Kotlin
... class SettingsActivityTest { ... @BindValue @ExampleQualifier @Mock lateinit var qualifiedVariable: ExampleCustomType // Robolectric tests here }
Java
... class SettingsActivityTest { ... @BindValue @ExampleQualifier @Mock ExampleCustomType qualifiedVariable; // Robolectric tests here }
अगर आपको मल्टीबाइंडिंग जोड़नी है, तो @BindValue
के बजाय @BindValueIntoSet
और @BindValueIntoMap
एनोटेशन का इस्तेमाल किया जा सकता है. @BindValueIntoMap
के लिए, आपको मैप की मुख्य जानकारी वाले एनोटेशन की मदद से, फ़ील्ड पर एनोटेट भी करना होगा.
विशेष मामले
Hilt, इस्तेमाल के ग़ैर-स्टैंडर्ड उदाहरणों के लिए भी सुविधाएं उपलब्ध कराता है.
जांच के लिए कस्टम ऐप्लिकेशन
अगर HiltTestApplication
का इस्तेमाल नहीं किया जा सकता, क्योंकि आपके टेस्ट ऐप्लिकेशन को किसी दूसरे ऐप्लिकेशन को एक्सटेंंड करना है, तो @CustomTestApplication
के साथ किसी नई क्लास या इंटरफ़ेस को एनोटेट करें. इसके लिए, उस बेस क्लास की वैल्यू पास करें जिसे जनरेट किए गए Hilt ऐप्लिकेशन को एक्सटेंंड करना है.
@CustomTestApplication
, Hilt की मदद से जांच के लिए तैयार Application
क्लास जनरेट करेगा. यह क्लास, पैरामीटर के तौर पर पास किए गए ऐप्लिकेशन को बढ़ाती है.
Kotlin
@CustomTestApplication(BaseApplication::class) interface HiltTestApplication
Java
@CustomTestApplication(BaseApplication.class) interface HiltTestApplication { }
उदाहरण में, Hilt HiltTestApplication_Application
क्लास को एक्सटेंड करने वाला 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
लाइब्रेरी से launchFragmentInContainer
का इस्तेमाल नहीं किया जा सकता, क्योंकि यह ऐसी गतिविधि पर निर्भर करती है जिसे @AndroidEntryPoint
से एनोटेट नहीं किया गया है.
इसके बजाय, architecture-samples
GitHub रिपॉज़िटरी में मौजूद launchFragmentInHiltContainer
कोड का इस्तेमाल करें.
सिंगलटन कॉम्पोनेंट उपलब्ध होने से पहले, एंट्री पॉइंट का इस्तेमाल करना
@EarlyEntryPoint
एनोटेशन, Hilt टेस्ट में सिंगलटन कॉम्पोनेंट उपलब्ध होने से पहले, Hilt एंट्री पॉइंट बनाने के लिए एक 'इस्केप हैच' उपलब्ध कराता है.
@EarlyEntryPoint
के बारे में ज़्यादा जानकारी के लिए,
Hilt के दस्तावेज़ देखें.