Already referred this very similar issue.
I am trying to write my first coroutine test.
Getting this error,
Exception in thread "Test worker @coroutine#1"
java.lang.NullPointerException at <app_package_name>.data.source.usecase.GetSourcesCountUseCase.invoke(GetSourcesCountUseCase.kt:10)
Unit Test code
class AddTransactionScreenViewModelImplTest {
@get:Rule
val mainDispatcherRule = MainDispatcherRule()
private val dataStore: MyDataStore = mock()
private val getCategoriesUseCase: GetCategoriesUseCase = mock()
private val getSourcesUseCase: GetSourcesUseCase = mock()
private val getTitleSuggestionsUseCase: GetTitleSuggestionsUseCase = mock()
private val navigationManager: NavigationManager = mock()
private val dispatcherProvider: DispatcherProvider = TestDispatcherProviderImpl(
testDispatcher = mainDispatcherRule.testDispatcher,
)
private val getSourcesCountUseCase: GetSourcesCountUseCase = mock()
private val insertTransactionUseCase: InsertTransactionUseCase = mock()
private val updateSourcesUseCase: UpdateSourcesUseCase = mock()
private lateinit var addTransactionScreenViewModel: AddTransactionScreenViewModel
@Before
fun setUp() {
addTransactionScreenViewModel = AddTransactionScreenViewModelImpl(
dataStore = dataStore,
getCategoriesUseCase = getCategoriesUseCase,
getSourcesUseCase = getSourcesUseCase,
getTitleSuggestionsUseCase = getTitleSuggestionsUseCase,
navigationManager = navigationManager,
dispatcherProvider = dispatcherProvider,
getSourcesCountUseCase = getSourcesCountUseCase,
insertTransactionUseCase = insertTransactionUseCase,
updateSourcesUseCase = updateSourcesUseCase,
)
}
@After
fun tearDown() {
}
@Test
fun getTransactionTypesForNewTransaction(): Unit = runTest {
whenever(
getSourcesCountUseCase.invoke()
).thenReturn(1)
whenever(
getSourcesUseCase.invoke()
).thenReturn(
flow {
emptyList<Source>()
},
)
whenever(
getCategoriesUseCase.invoke()
).thenReturn(
flow {
emptyList<Category>()
},
)
val result: List<TransactionType> = addTransactionScreenViewModel
.transactionTypesForNewTransaction.first()
Assert.assertEquals(
arrayOf(
TransactionType.INCOME,
TransactionType.EXPENSE,
TransactionType.TRANSFER
),
result,
)
}
}
Code I am testing
override val transactionTypesForNewTransaction: StateFlow<List<TransactionType>> = flow {
val sourceCount = getSourcesCountUseCase()
val transactionTypesForNewTransaction = TransactionType.values().filter {
if (sourceCount > 1) {
it != TransactionType.ADJUSTMENT
} else {
it != TransactionType.ADJUSTMENT && it != TransactionType.TRANSFER
}
}
emit(
value = transactionTypesForNewTransaction,
)
}.defaultListStateIn()
MainDispatcherRule (Source)
class MainDispatcherRule(
val testDispatcher: TestDispatcher = UnconfinedTestDispatcher(),
) : TestWatcher() {
override fun starting(description: Description) {
Dispatchers.setMain(testDispatcher)
}
override fun finished(description: Description) {
Dispatchers.resetMain()
}
}
TestDispatcherProviderImpl
class TestDispatcherProviderImpl(
testDispatcher: TestDispatcher,
) : DispatcherProvider {
override val main: CoroutineDispatcher = testDispatcher
override val io: CoroutineDispatcher = testDispatcher
override val default: CoroutineDispatcher = testDispatcher
override val unconfined: CoroutineDispatcher = testDispatcher
}
DispatcherProvider
interface DispatcherProvider {
val main: CoroutineDispatcher
val io: CoroutineDispatcher
val default: CoroutineDispatcher
val unconfined: CoroutineDispatcher
}