I am trying to mock a response from my usecases, this usecase works with coroutines.
fun getData() {
view?.showLoading()
getProductsUseCase.execute(this::onSuccessApi, this::onErrorApi)
}
My useCase is injected on presenter.
GetProductsUseCase has this code:
class GetProductsUseCase (private var productsRepository: ProductsRepository) : UseCase<MutableMap<String, Product>>() {
override suspend fun executeUseCase(): MutableMap<String, Product> {
val products =productsRepository.getProductsFromApi()
return products
}
}
My BaseUseCase
abstract class UseCase<T> {
abstract suspend fun executeUseCase(): Any
fun execute(
onSuccess: (T) -> Unit,
genericError: () -> Unit) {
GlobalScope.launch {
val result = async {
try {
executeUseCase()
} catch (e: Exception) {
GenericError()
}
}
GlobalScope.launch(Dispatchers.Main) {
when {
result.await() is GenericError -> genericError()
else -> onSuccess(result.await() as T)
}
}
}
}
}
This useCase call my repository:
override suspend fun getProductsFromApi(): MutableMap<String, Product> {
val productsResponse = safeApiCall(
call = {apiService.getProductsList()},
error = "Error fetching products"
)
productsResponse?.let {
return productsMapper.fromResponseToDomain(it)!!
}
return mutableMapOf()
}
Y try to mock my response but test always fails.
@RunWith(MockitoJUnitRunner::class)
class HomePresenterTest {
lateinit var presenter: HomePresenter
@Mock
lateinit var view: HomeView
@Mock
lateinit var getProductsUseCase: GetProductsUseCase
@Mock
lateinit var updateProductsUseCase: UpdateProductsUseCase
private lateinit var products: MutableMap<String, Product>
private val testDispatcher = TestCoroutineDispatcher()
private val testScope = TestCoroutineScope(testDispatcher)
@Mock
lateinit var productsRepository:ProductsRepositoryImpl
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
products = ProductsMotherObject.createEmptyModel()
presenter = HomePresenter(view, getProductsUseCase, updateProductsUseCase, products)
}
@After
fun after() {
Dispatchers.resetMain()
testScope.cleanupTestCoroutines()
}
//...
@Test
fun a() = testScope.runBlockingTest {
setTasksNotAvailable(productsRepository)
presenter.getDataFromApi()
verify(view).setUpRecyclerView(products.values.toMutableList())
}
private suspend fun setTasksNotAvailable(dataSource: ProductsRepository) {
`when`(dataSource.getProductsFromApi()).thenReturn((mutableMapOf()))
}
}
I don't know what is happening. The log says:
"Wanted but not invoked:
view.setUpRecyclerView([]);
-> at com.myProject.HomePresenterTest$a$1.invokeSuspend(HomePresenterTest.kt:165)
However, there was exactly 1 interaction with this mock:
view.showLoading();"
The problem is with how you create your GetProductsUseCase
.
You're not creating it with the mocked
version of your ProductsRepository
, yet you're mocking the ProductsRepository
calls.
Try to create the GetProductsUseCase
manually and not using a @Mock
// no @Mock
lateinit var getProductsUseCase: GetProductsUseCase
@Before
fun setUp() {
// ...
// after your mocks are initialized...
getProductsUseCase = GetProductsUseCase(productsRepository) //<- this uses mocked ProductsRepository
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With