אחד היתרונות של שימוש במסגרות להחדרת תלות כמו Hilt הוא שקל יותר לבדוק את הקוד.
בדיקות יחידה
אין צורך ב-Hilt לבדיקות יחידה, כי כשבודקים מחלקה שמשתמשת בהזרקת בנאי, לא צריך להשתמש ב-Hilt כדי ליצור מופע של המחלקה הזו. במקום זאת, אפשר לקרוא ישירות לקונסטרוקטור של מחלקה על ידי העברת תלויות מזויפות או מדומה, בדיוק כמו שהייתם עושים אם הקונסטרוקטור לא היה מסומן בהערה:
@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(...) } }
אותו עיקרון חל על מחלקות ViewModel שמתקבלות על ידי קריאה ל-hiltViewModel() בקומפוזיציות. בבדיקות יחידה, יוצרים את ViewModel ישירות עם נתונים מזויפים.
למידע על אופן העברת מצב מ-ViewModel לרכיבים קומפוזביליים, אפשר לעיין במאמרים מצב ו-Jetpack פיתוח נייטיב ואיפה כדאי להעביר מצב.
בדיקות מקצה לקצה
בבדיקות שילוב, Hilt מחדיר תלויות כמו בקוד הייצור. אין צורך בתחזוקה של בדיקות עם Hilt כי Hilt יוצר באופן אוטומטי קבוצה חדשה של רכיבים לכל בדיקה.
הוספת יחסי תלות לבדיקה
כדי להשתמש ב-Hilt בבדיקות, צריך לכלול את התלות hilt-android-testing בפרויקט:
dependencies { // For Robolectric tests. testImplementation("com.google.dagger:hilt-android-testing:2.57.1") kspTest("com.google.dagger:hilt-android-compiler:2.57.1") // For instrumented tests. androidTestImplementation("com.google.dagger:hilt-android-testing:2.57.1") kspAndroidTest("com.google.dagger:hilt-android-compiler:2.57.1") // Compose UI test rule. androidTestImplementation("androidx.compose.ui:ui-test-junit4") debugImplementation("androidx.compose.ui:ui-test-manifest") }
הגדרת בדיקת ממשק משתמש
צריך להוסיף את ההערה @HiltAndroidTest לכל בדיקת ממשק משתמש שמשתמשת ב-Hilt. ההערה
הזו אחראית ליצירת רכיבי Hilt לכל בדיקה.
בנוסף, צריך להוסיף את HiltAndroidRule לכיתת הבדיקה. הוא מנהל את מצב הרכיבים ומשמש להחדרה בבדיקה:
@HiltAndroidTest class SettingsScreenTest { @get:Rule(order = 0) val hiltRule = HiltAndroidRule(this) @get:Rule(order = 1) val composeRule = createAndroidComposeRule<HiltTestActivity>() // Compose UI tests here. }
בשלב הבא, הבדיקה צריכה לדעת על המחלקה Application ש-Hilt יוצרת באופן אוטומטי בשבילכם.
כדי לאפשר ל-Hilt להוסיף תלויות, צריך ליצור פעילות ריקה בשם HiltTestActivity בערכת המקור androidTest ולהוסיף לה את ההערה @AndroidEntryPoint. createAndroidComposeRule משתמש בפעילות הזו כמארח של התוכן המורכב.
אפליקציית בדיקה
צריך להריץ בדיקות עם מכשור שמשתמשות ב-Hilt באובייקט Application שתומך ב-Hilt. הספרייה מספקת HiltTestApplication לשימוש בבדיקות.
אם אתם צריכים אפליקציית בסיס אחרת לניסויים, תוכלו לעיין במאמר בנושא אפליקציה בהתאמה אישית לניסויים.
צריך להגדיר את אפליקציית הבדיקה כך שתפעל בבדיקות עם מכשור או בבדיקות Robolectric. ההוראות הבאות לא ספציפיות ל-Hilt, אלא הן הנחיות כלליות לגבי ציון אפליקציה בהתאמה אישית להרצה בבדיקות.
הגדרת אפליקציית הבדיקה בבדיקות עם מכשור
כדי להשתמש באפליקציית הבדיקה של Hilt בבדיקות עם מכשור, צריך להגדיר רכיב חדש להרצת בדיקות. כך Hilt פועל בכל הבדיקות המכשירות בפרויקט. מבצעים את השלבים הבאים:
- יוצרים מחלקה בהתאמה אישית שמרחיבה את
AndroidJUnitRunnerבתיקייהandroidTest. - מבטלים את ההגדרה של הפונקציה
newApplicationומעבירים את השם של אפליקציית הבדיקה שנוצרה ב-Hilt.
// 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) } }
לאחר מכן, מגדירים את כלי ההרצה הזה בקובץ Gradle, כמו שמתואר במדריך בנושא בדיקות יחידה עם מכשור. חשוב לוודא שמשתמשים בנתיב המלא של המחלקה:
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:
@HiltAndroidTest @Config(application = HiltTestApplication::class) class SettingsScreenTest { @get:Rule var hiltRule = HiltAndroidRule(this) // Robolectric tests here. }
בדיקת תכונות
אחרי ש-Hilt מוכן לשימוש בבדיקות, אפשר להשתמש בכמה תכונות כדי להתאים אישית את תהליך הבדיקה.
החדרת סוגים לבדיקות
כדי להוסיף סוגים לבדיקה, משתמשים ב-@Inject להוספת שדות. כדי להורות ל-Hilt לאכלס את השדות @Inject, קוראים ל-hiltRule.inject().
לדוגמה, כך נראה מבחן עם מכשור:
@HiltAndroidTest class SettingsScreenTest { @get:Rule(order = 0) val hiltRule = HiltAndroidRule(this) @get:Rule(order = 1) val composeRule = createAndroidComposeRule<HiltTestActivity>() @Inject lateinit var analyticsAdapter: AnalyticsAdapter @Before fun init() { hiltRule.inject() } @Test fun settingsScreen_showsTitle() { composeRule.setContent { SettingsScreen() } composeRule.onNodeWithText("Settings").assertIsDisplayed() // analyticsRepository is available here. } }
החלפת קישור נתונים
אם אתם צריכים להחדיר מופע מזויף או מדומה של תלות, אתם צריכים להגיד ל-Hilt לא להשתמש בקשר שהוא השתמש בו בקוד הייצור, אלא להשתמש בקשר אחר. כדי להחליף קישור, צריך להחליף את המודול שמכיל את הקישור במודול בדיקה שמכיל את הקישורים שרוצים להשתמש בהם בבדיקה.
לדוגמה, נניח שקוד הייצור שלכם מגדיר קישור ל-AnalyticsService באופן הבא:
@Module @InstallIn(SingletonComponent::class) abstract class AnalyticsModule { @Singleton @Binds abstract fun bindAnalyticsService( analyticsServiceImpl: AnalyticsServiceImpl ): AnalyticsService }
כדי להחליף את הקישור AnalyticsService בבדיקות, יוצרים מודול Hilt חדש בתיקייה test או androidTest עם התלות המדומה ומסמנים אותו באמצעות @TestInstallIn. במקום זאת, כל הבדיקות בתיקייה הזו מקבלות את התלות המזויפת.
@Module @TestInstallIn( components = [SingletonComponent::class], replaces = [AnalyticsModule::class] ) abstract class FakeAnalyticsModule { @Singleton @Binds abstract fun bindAnalyticsService( fakeAnalyticsService: FakeAnalyticsService ): AnalyticsService }
בדרך כלל, פונקציות composable צורכות את התלות האלה באופן עקיף דרך ViewModel שמתקבל באמצעות hiltViewModel(), ולכן מספיק להחליף את הקישור ב-Hilt. הקומפוזבילי שנבדק מזהה את הזיוף באופן אוטומטי.
החלפת קשירה בבדיקה יחידה
כדי להחליף קשירה בבדיקה אחת במקום בכל הבדיקות, מסירים התקנה של מודול Hilt מבדיקה באמצעות ההערה @UninstallModules ויוצרים מודול בדיקה חדש בתוך הבדיקה.
בהמשך לדוגמה AnalyticsService מהגרסה הקודמת, מתחילים בהוראה ל-Hilt להתעלם ממודול הייצור באמצעות ההערה @UninstallModules בכיתת הבדיקה:
@UninstallModules(AnalyticsModule::class) @HiltAndroidTest class SettingsScreenTest { ... }
בשלב הבא, צריך להחליף את הקישור. יוצרים מודול חדש בתוך מחלקת הבדיקה שמגדיר את קישור הבדיקה:
@UninstallModules(AnalyticsModule::class) @HiltAndroidTest class SettingsScreenTest { @Module @InstallIn(SingletonComponent::class) abstract class TestModule { @Singleton @Binds abstract fun bindAnalyticsService( fakeAnalyticsService: FakeAnalyticsService ): AnalyticsService } // ... }
הפעולה הזו מחליפה את הקישור רק עבור מחלקת בדיקה אחת. אם רוצים להחליף את הקישור לכל מחלקות הבדיקה, משתמשים בהערה @TestInstallIn מהקטע שלמעלה. לחלופין, אפשר להוסיף את הקישור לבדיקה למודול test לבדיקות Robolectric, או למודול androidTest לבדיקות עם מכשור.
ההמלצה היא להשתמש ב-@TestInstallIn בכל הזדמנות.
קישור ערכים חדשים
אפשר להשתמש בהערה @BindValue כדי לקשר בקלות שדות בבדיקה לגרף התלות של Hilt. אם מוסיפים לשדה את ההערה @BindValue, השדה יקבל את סוג השדה שהוגדר לו עם כל המאפיינים שקיימים בשדה הזה.
בדוגמה AnalyticsService, אפשר להחליף את AnalyticsService בזיוף באמצעות @BindValue:
@UninstallModules(AnalyticsModule::class) @HiltAndroidTest class SettingsScreenTest { @BindValue @JvmField val analyticsService: AnalyticsService = FakeAnalyticsService() ... }
כך אפשר גם להחליף את הקישור וגם להפנות אליו בבדיקה, ולעשות את שתי הפעולות בו-זמנית.
@BindValue פועל עם מסננים והערות אחרות לבדיקה. לדוגמה, אם משתמשים בספריות בדיקה כמו Mockito, אפשר להשתמש בה בבדיקת Robolectric באופן הבא:
... class SettingsScreenTest { ... @BindValue @ExampleQualifier @Mock lateinit var qualifiedVariable: ExampleCustomType // Robolectric tests here }
אם אתם צריכים להוסיף multibinding, אתם יכולים להשתמש באנוטציות @BindValueIntoSet ו-@BindValueIntoMap במקום @BindValue. @BindValueIntoMap מחייב גם להוסיף לשדה הערה של מפתח מפה.
מקרים מיוחדים
Hilt מספק גם תכונות לתמיכה בתרחישי שימוש לא סטנדרטיים.
אפליקציה מותאמת אישית לבדיקות
אם אתם לא יכולים להשתמש ב-HiltTestApplication כי אפליקציית הבדיקה שלכם צריכה להרחיב אפליקציה אחרת, אתם יכולים להוסיף הערה למחלקה או לממשק חדשים עם @CustomTestApplication, ולהעביר את הערך של מחלקת הבסיס שאתם רוצים שאפליקציית Hilt שנוצרה תרחיב.
@CustomTestApplication ייצור מחלקה Application שמוכנה לבדיקה באמצעות Hilt, שמרחיבה את האפליקציה שהעברתם כפרמטר.
@CustomTestApplication(BaseApplication::class) interface HiltTestApplication
בדוגמה, Hilt יוצר רכיב בשם Application שהוא הרחבה של המחלקה BaseApplication.HiltTestApplication_Application בדרך כלל, השם של האפליקציה שנוצרת הוא השם של המחלקה עם ההערות בתוספת _Application. צריך להגדיר את אפליקציית הבדיקה שנוצרה על ידי Hilt כך שתפעל בבדיקות עם מכשור או בבדיקות Robolectric, כמו שמתואר במאמר אפליקציית בדיקה.
אובייקטים מרובים של TestRule בבדיקה המכשירה
בבדיקות של ממשק משתמש ב-Compose כבר משולב HiltAndroidRule עם כלל בדיקה ב-Compose, כמו createAndroidComposeRule. אם יש לכם עוד אובייקטים של TestRule, הקפידו להריץ קודם את HiltAndroidRule. מגדירים את סדר ההרצה באמצעות המאפיין order ב-@Rule:
@HiltAndroidTest class SettingsScreenTest { @get:Rule(order = 0) var hiltRule = HiltAndroidRule(this) @get:Rule(order = 1) val composeRule = createAndroidComposeRule<HiltTestActivity>() @get:Rule(order = 2) val otherRule = SomeOtherRule() // UI tests here. }
אפשר גם להוסיף את הכללים בין התגים RuleChain, ולהציב את התג HiltAndroidRule ככלל החיצוני.
@HiltAndroidTest class SettingsScreenTest { @get:Rule var rule = RuleChain.outerRule(HiltAndroidRule(this)). around(SettingsScreenTestRule(...)) // UI tests here. }
שימוש בנקודת כניסה לפני שהרכיב היחיד זמין
ההערה @EarlyEntryPoint מספקת פתרון כשצריך ליצור נקודת כניסה של Hilt לפני שרכיב הסינגלטון זמין בבדיקת Hilt.
מידע נוסף על @EarlyEntryPoint זמין במאמרי העזרה בנושא Hilt.
מקורות מידע נוספים
מידע נוסף על בדיקות זמין במקורות המידע הבאים: