אחד מהיתרונות של השימוש ב-frameworks של הזרקת תלות, כמו 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 יוצר באופן אוטומטי קבוצה חדשה של רכיבים לכל בדיקה.
הוספת יחסי תלות לבדיקה
כדי להשתמש ב-Hhilt בבדיקות, צריך לכלול בפרויקט את התלות 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") }
הגדרה של בדיקת ממשק המשתמש
צריך להוסיף הערה לכל בדיקת ממשק משתמש שמשתמשת ב-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
לחלופין, אפשר להגדיר את האפליקציה בכל בדיקה בנפרד באמצעות ההערה @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. }
אם אתם משתמשים ב-Android Gradle Plugin בגרסה נמוכה מ-4.2, תוכלו להפעיל את הטרנספורמציה של כיתות @AndroidEntryPoint
בבדיקות יחידה מקומיות על ידי החלת ההגדרה הבאה בקובץ build.gradle
של המודול:
מגניב
hilt { enableTransformForLocalTests = true }
Kotlin
hilt { enableTransformForLocalTests = true }
מידע נוסף על enableTransformForLocalTests
זמין במסמכי התיעוד של Hilt.
בדיקת תכונות
אחרי ש-Hilt מוכן לשימוש בבדיקות, אפשר להשתמש בכמה תכונות כדי להתאים אישית את תהליך הבדיקה.
הזרקת סוגים בבדיקות
כדי להזריק סוגים לבדיקה, צריך להשתמש ב-@Inject
להחדרת שדה. כדי להורות ל-Hhilt לאכלס את השדות @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
בבדיקות, יוצרים מודול 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
ב-@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
פועל עם מכשירים למיון (qualifiers) והערות בדיקה אחרות. לדוגמה, אם אתם משתמשים בספריות בדיקה כמו 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. }
launchFragmentInContainer
אי אפשר להשתמש ב-launchFragmentInContainer
מהספרייה androidx.fragment:fragment-testing
עם Hilt, כי הוא מסתמך על פעילות שלא נוספה לה הערה @AndroidEntryPoint
.
במקום זאת, צריך להשתמש בקוד launchFragmentInHiltContainer
מהמאגר ב-GitHub architecture-samples
.
צריך להשתמש בנקודת כניסה לפני שרכיב הסינגלטון זמין
ההערה @EarlyEntryPoint
מספקת פתח מילוט כשצריך ליצור נקודת כניסה ל-Hilt לפני שהרכיב מסוג singleton יהיה זמין בבדיקת Hilt.
מידע נוסף על @EarlyEntryPoint
זמין במסמכי התיעוד של Hilt.