# Unit Test - 使用hilt測試9 - Testing Add Item
---
## 開始吧
### 情境
### 修改AddShoppingItemFragmen
* 注入glide
* 觀察者模式-當url變化.用glide讀取,insert data 做對應的動作
```kotlin=
class AddShoppingItemFragment @Inject constructor(
val glide: RequestManager //注入glide
) : Fragment(R.layout.fragment_add_shopping_item) {
lateinit var viewModel: ShoppingViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(requireActivity()).get(ShoppingViewModel::class.java)
subscribeToObserver()
btnAddShoppingItem.setOnClickListener {
viewModel.insertShoppingItem(
etShoppingItemName.text.toString(),
etShoppingItemAmount.text.toString(),
etShoppingItemPrice.text.toString()
)
}
ivShoppingImage.setOnClickListener {
findNavController().navigate(
AddShoppingItemFragmentDirections.actionAddShoppingItemFragmentToImagePickFragment()
)
}
val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
viewModel.setCurImageUrl("")
findNavController().popBackStack()
}
}
requireActivity().onBackPressedDispatcher.addCallback(callback)
}
private fun subscribeToObserver() {
viewModel.curImageUrl.observe(viewLifecycleOwner, Observer {
glide.load(it).into(ivShoppingImage)
})
viewModel.insertShoppingItemStatus.observe(viewLifecycleOwner, Observer {
it.getContentIfNotHandled()?.let { result ->
when (result.status) {
Status.SUCCESS -> {
Snackbar.make(
requireActivity().rootLayout,
"Add Shopping Item",
Snackbar.LENGTH_LONG
).show()
findNavController().popBackStack()
}
Status.ERROR -> {
Snackbar.make(
requireActivity().rootLayout,
result.message ?: "an unknown error occurred",
Snackbar.LENGTH_LONG
).show()
}
Status.LOADING -> {
/* NO-OP */
}
}
}
})
}
}
```
### 修正ShoppingFragmentFactory
* 增加glide的參數
```kotlin=
class ShoppingFragmentFactory @Inject constructor(
private val imageAdapter: ImageAdapter,
private val glide: RequestManager //注入用的
) : FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
return when (className) {
ImagePickFragment::class.java.name -> ImagePickFragment(imageAdapter)
//當實例化的fragment是底下這個,要傳遞glide做實例化
AddShoppingItemFragmen::class.java.name -> AddShoppingItemFragmen(glide)
else -> super.instantiate(classLoader, className)
}
}
}
```
### 寫測試吧
* 打開之前的AddShoppingItemFragmentTest
* 寫入一筆資料,並查詢DB是否有該筆資料
```kotlin=
@ExperimentalCoroutinesApi
@MediumTest
@HiltAndroidTest
class AddShoppingItemFragmentTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
@Before
fun setup() {
hiltRule.inject()
}
//新增factory
@Inject
lateinit var fragmentFactory: ShoppingFragmentFactory
//新增測試
@Test
fun clickInsertIntoDb_shoppingItemInsertedIntoDb() {
val testViewModel = ShoppingViewModel(FakeRepository())
launchFragmentInHiltContainer<AddShoppingItemFragment>(
fragmentFactory = fragmentFactory
) {
viewModel = testViewModel
}
onView(withId(R.id.etShoppingItemName)).perform(replaceText("shopping item"))
onView(withId(R.id.etShoppingItemAmount)).perform(replaceText("5"))
onView(withId(R.id.etShoppingItemPrice)).perform(replaceText("5.5"))
onView(withId(R.id.btnAddShoppingItem)).perform(click())
assertThat(testViewModel.shoppingItems.getOrAwaitValue())
.contains(ShoppingItem("shopping item", 5, 5.5f, ""))
}
@Test
fun pressBackButton_popBackStack() {
val navController = mock(NavController::class.java)
launchFragmentInHiltContainer<AddShoppingItemFragment> {
Navigation.setViewNavController(requireView(), navController)
}
pressBack()
verify(navController).popBackStack()
}
@Test
fun clickivShoppingImage_navigeteToImagePickFragment() {
val navController = mock(NavController::class.java)
launchFragmentInHiltContainer<AddShoppingItemFragment> {
Navigation.setViewNavController(requireView(), navController)
}
onView(withId(R.id.ivShoppingImage)).perform(click())
verify(navController).navigate(
AddShoppingItemFragmentDirections.actionAddShoppingItemFragmentToImagePickFragment()
)
}
@Test
fun imageUrlIsEmpty_afterPooBackStack() {
val testviewModel = ShoppingViewModel(FakeRepository())
val navController = mock(NavController::class.java)
launchFragmentInHiltContainer<AddShoppingItemFragment> {
Navigation.setViewNavController(requireView(), navController)
viewModel = testviewModel
}
pressBack()
val value = testviewModel.curImageUrl.getOrAwaitValue()
assertThat(value).isEmpty()
}
}
```

參考資料
[
Philipp Lackner's channel](https://www.youtube.com/watch?v=6ZQ9v0KFiPA)
###### tags: `test` `Unit Test` `kotlin` `hilt`