# Unit Test - 使用hilt測試5 - 改寫Dao Testing --- ## 開始吧 ### 情境 在[這一篇](https://hackmd.io/QPN8oKVWTj6EkD2y0h7UuQ?view) 我們用一般的方法,在每次測試前產生database instanse,這次要改成使用DI ### 新增dependencies ```kotlin= //hilt_version = 2.37 //hilt for test androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_version" kaptAndroidTest "com.google.dagger:hilt-compiler:$hilt_version" ``` ### 定義HiltTestRunner * 因為Database會用到application * 使用hilt測試application需要自定義Test runner * 在androidTest目錄下新建類別如下 ```kotlin= class HiltTestRunner: AndroidJUnitRunner() { override fun newApplication( cl: ClassLoader?, className: String?, context: Context? ): Application { //第二個參數className改成下面HiltTestApplication::class.java.name return super.newApplication(cl, HiltTestApplication::class.java.name, context) } } ``` ### 把test Runner指定到剛剛建立的HiltTestRunner ```kotlin= // Gradle Module defaultConfig { applicationId "com.androiddevs.shoppinglisttestingyt" minSdkVersion 21 targetSdkVersion 30 versionCode 1 versionName "1.0" **替換掉** // testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "com.androiddevs.shoppinglisttestingyyt.HiltTestRunner" } ``` ### 移除舊有的JUnit Runner * 移除RunWith,因為我們已經指定到hiltTestRunner ```kotlin= @ExperimentalCoroutinesApi @RunWith(AndroidJUnit4::class) //這一行移除 @SmallTest class ShoppingDaoTest { } ``` ### 新增Module來提供database * 新增package di * 新增物件TestAppModule * 這邊使用@Named()是要讓hilt知道要使用哪個Module提供instance,正常來說我們會有一個app使用的Module也會提供database instance,所以使用@Named指定 ```kotlin= @Module @InstallIn(SingletonComponent::class) object TestAppModule { @Provides @Named("test_db") fun provideInMemoryDb(@ApplicationContext context: Context) = Room.inMemoryDatabaseBuilder(context, ShoppingItemDatabase::class.java) .allowMainThreadQueries() .build() } ``` ### Dao refactor * 加入聲明@HiltAndroidTest * 新增Rule ```kotlin= @ExperimentalCoroutinesApi @SmallTest @HiltAndroidTest class ShoppingDaoTest { //for hilt rule @get:Rule var hiltRule = HiltAndroidRule(this) @get:Rule var instantTaskExecutorRule = InstantTaskExecutorRule() //注入Database,著名是test_db,這樣它才知道要去TestAppModule拿instance @Inject @Named("test_db") lateinit var database: ShoppingItemDatabase private lateinit var dao: ShoppingDao @Before fun setUp() { //初始化提供注入 取代原本在這裡初始化database hiltRule.inject() dao = database.shoppingDao() } } ``` ### 跑測試吧... * ~~很遺憾.....跑不出來.......~~ * ~~根據官方說法[Android studio run test not working](https://dagger.dev/hilt/gradle-setup.html#running-with-android-studio)~~ * ~~除了dependency版本要match以外,看來test還有些許限制跟bug未解~~ * ~~[等解bug吧](https://issuetracker.google.com/issues/37076369?pli=1)~~ ![](https://i.imgur.com/79ztoMv.png) ## 期待hilt更完善吧~~~~:joy_cat::joy_cat::joy_cat::joy_cat::joy_cat: ### 發現手誤 * 多打了一個y ```kotlin= //之前打錯的路徑 testInstrumentationRunner "com.androiddevs.shoppinglisttestingyyt.HiltTestRunner" //修正後的路徑 testInstrumentationRunner "com.androiddevs.shoppinglisttestingyt.HiltTestRunner" ``` ![](https://i.imgur.com/yLmHHUg.png) ###### tags: `test` `Unit Test` `hilt` `kotlin`