تتمثل إحدى فوائد استخدام أطر عمل حقن التبعية مثل 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
وتمرير اسم الدالة التي تم إنشاؤها تطبيق اختبار 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 كما هو موضح في اختبار وحدة قياس حالة الدليل. يُرجى التأكد من أنّ: فإنك تستخدم مسار الفئة الكامل:
رائع
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's @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)
المستندات.
ميزات الاختبار
بعد أن تصبح Hilt جاهزة للاستخدام في اختباراتك، يمكنك استخدام عدة ميزات لإجراء ما يلي: تخصيص عملية الاختبار.
أنواع الحقن في الاختبارات
لحقن الأنواع في اختبار، استخدِم @Inject
لحقن الحقل. لتطلب من "هيلت"
املأ حقول @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
في الاختبارات، أنشِئ وحدة 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
من النسخة السابقة، ابدأ بإخبار
انقر لتجاهل وحدة الإنتاج باستخدام التعليق التوضيحي @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
بـ
زائفًا باستخدام @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
. ضِمن
عام، يكون اسم التطبيق الذي تم إنشاؤه هو اسم التطبيق الذي تم إنشاؤه بتعليقات توضيحية
تم إلحاق الصف بالصف _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
. لا تعمل هذه الميزة إلا في إصدار 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. }
إطلاقFragmentInContainer
لا يمكن استخدام launchFragmentInContainer
من مكتبة
androidx.fragment:fragment-testing
مع Hilt، لأنّه يعتمد على
نشاط لم يتمّت إضافة تعليقات توضيحية إليه باستخدام @AndroidEntryPoint
.
يمكنك استخدام
launchFragmentInHiltContainer
التعليمة البرمجية من
architecture-samples
GitHub
المستودع بدلاً من ذلك.
استخدام نقطة دخول قبل أن يصبح المكوِّن المفردتون متاحًا
يوفّر التعليق التوضيحي @EarlyEntryPoint
بوابة هروب عند استخدام Hilt.
قبل أن يصبح المكون المفردتون متاحًا في
اختبار Hilt
مزيد من المعلومات حول "@EarlyEntryPoint
" في
مستندات النتيجة: