من بين مزايا استخدام إطارات عمل حقن التبعية، مثل 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
في
مشروعك:
رائع
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") }
إعداد اختبار واجهة المستخدم
يجب إضافة تعليقات توضيحية إلى أي اختبار لواجهة المستخدم يستخدم Hilt مع @HiltAndroidTest
. هذا التعليق التوضيحي
مسؤول عن إنشاء مكونات 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 لجميع الاختبارات المُزوّدة بأدوات قياس الأداء في مشروعك. اتّبِع الخطوات التالية:
- أنشئ فئة مخصّصة تمتد إلى
AndroidJUnitRunner
في المجلدandroidTest
. - يمكنك إلغاء الدالة
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
بدلاً من ذلك، يمكنك ضبط التطبيق في كل اختبار على حدة باستخدام التعليق التوضيحي @Config
في Robolectric:
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. }
إذا كنت تستخدم إصدارًا أقدم من 4.2 من "مكوّن إضافي لـ Gradle في Android"، فعِّل
تحويل فئات @AndroidEntryPoint
في اختبارات الوحدات المحلية من خلال تطبيق الإعدادات التالية في ملف build.gradle
الخاص بوحدتك:
رائع
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. } }
استبدال رابط
إذا كنت بحاجة إلى إدخال مثيل مزيّف أو وهمي لمكوّن تابع، عليك إخبار IDE 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
في الاختبارات، أنشئ وحدة Hilt جديدة في
المجلد 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
من الإصدار السابق، ابدأ بطلب
من 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
من
القسم أعلاه. بدلاً من ذلك، يمكنك وضع ربط الاختبار في وحدة test
لاختبارات Robolectric، أو في وحدة androidTest
للاختبارات المستندة إلى أدوات القياس.
وننصحك باستخدام @TestInstallIn
كلما أمكن.
ربط قيم جديدة
استخدِم التعليق التوضيحي @BindValue
لربط الحقول في اختبارك بسهولة بالرسم البياني لتبعية Hilt. أضِف تعليقًا توضيحيًا إلى حقل باستخدام @BindValue
، وسيتم ربطه ضمن
نوع الحقل المُعلَن باستخدام أيّ محددات متوفّرة لذلك الحقل.
في مثال AnalyticsService
، يمكنك استبدال AnalyticsService
بعبارة
fake باستخدام @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، يمكنك استخدامها في اختبار
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 }
إذا كنت بحاجة إلى إضافة ربط متعدد،
يمكنك استخدام التعليقَين التوضيحيَين @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
. بشكلٍ عام، اسم التطبيق الذي تم إنشاؤه هو اسم ال annotated
class المُرفَق بـ _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
أولاً. حدِّد ترتيب التنفيذ باستخدام سمة
order
في التعليق التوضيحي @Rule
. لا يعمل هذا الإجراء إلا في الإصدار 4.13 من JUnit أو الإصدارات الأحدث:
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
لا يمكن استخدام launchFragmentInContainer
من مكتبة
androidx.fragment:fragment-testing
مع Hilt، لأنّه يعتمد على
نشاط لم يتمّت إضافة تعليقات توضيحية إليه باستخدام @AndroidEntryPoint
.
استخدِم رمز
launchFragmentInHiltContainer
من مستودع GitHub
architecture-samples
بدلاً من ذلك.
استخدام نقطة دخول قبل توفّر المكوّن الفردي
يقدّم التعليق التوضيحي @EarlyEntryPoint
مخرجًا عند الحاجة إلى إنشاء نقطة دخول
Hilt قبل توفّر المكوّن الفردي في اختبار
Hilt.
يمكنك الاطّلاع على مزيد من المعلومات عن @EarlyEntryPoint
في
مستندات Hilt.