I tried many references available regarding the same but nothing worked.
I have a method in Kotlin which can throws Checked and unchecked exceptions both(depend on which block in throwing the exception)
fun deleteItem(tokens: List<String>, userId: Long) {
val records = storeRegistry.readItemsByTokens(tokens)
val missingTokens = tokens.toSet() - records.map { it.token }.toSet()
if (missingTokens.isNotEmpty()) {
throw EntityNotFoundException( // checked exception
"Item with tokens=$missingTokens does not exist."
)
}
transactionManager.executeInTransaction {
tokens.forEach {
val success = storeRegistry.deleteItemByToken(it, userId)
if (!success) {
throw InternalException.badRequest( // unchecked exception
"Item delete failed: item token=$it"
)
}
}
}
}
This method is called from some other's class method which is in test. and Unit test look like this
#Test
fun deleteItemShouldThrowIfEntityNotFound() {
whenever(ItemManager.deleteItemsByTokens(any(), any()))
.thenAnswer { throw EntityNotFoundException() }
val deleteRequest = ItemsDeleteRequest.builder()
.ItemsDeleteParams(
listOf(
ItemDeleteParams.createToken("token1"),
ItemDeleteParams.createToken("token2"),
)
).build()
// act
try {
getAfterburner().ignite(
buildServiceRequest(deleteRequest),
DEFAULT_TEST_TIMEOUT
).join()
} catch (e: Exception) {
assert(e.cause is EntityNotFoundException)
}
verify(ItemManager, times(1))
.deleteItemsByTokens(listOf("token1", "token2"), 123456L)
}
When I run above test, I got this error
org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: com.abc.xtz.api.EntityNotFoundException
Mockito won't throw a checked exception for a function that doesn't have the checked exception as part of its signature. To be able to do this, you need to add the checked exception to the function signature using #Throws:
#Throws(EntityNotFoundException::class)
fun deleteItem(tokens: List<String>, userId: Long) {
//...
Related
updated kotlinx-coroutines-test-jvm-1.6.1.jar and with a lot of changes, it seems I can't clarify how to test exception handling in unit test.
#Test
fun `unblock profile which throws exception`() = runTest {
val vm = createViewModel(StandardTestDispatcher(testScheduler))
val handler = CoroutineExceptionHandler { _, t -> println(t.message) }
coEvery { connectionRepo.patchUnblockMember(FAKE_PROFILE_ID_1) }.throws(
IllegalArgumentException(DummyExceptionStr)
)
launch(testScheduler + handler) {
vm.errorState.collect {
assertThat(it).isIn(1..Int.MAX_VALUE)
return#collect
}
}
vm.unblockContact(fakeBlockedProfile1)
}
but exception is thrown every time, not able to handle it
This is my ViewModel and I want to throw an exception so to catch branch is executed.
class PopularSearchViewModel #Inject constructor(
private val popularSearchUseCase: LoadPopularSearchUseCase,
private val coroutineDispatcherProvider: CoroutineDispatcherProvider
) :
ViewModel() {
private val listOfCatalogProductMutableStateFlow = MutableStateFlow<List<CatalogProduct>>(emptyList())
val listOfCatalogProductStateFlow = listOfCatalogProductMutableStateFlow.asStateFlow()
fun getPopularProducts() {
viewModelScope.launch(coroutineDispatcherProvider.io()) {
try {
listOfCatalogProductMutableStateFlow.value = popularSearchUseCase.execute()
} catch (exception: Exception) {
Timber.e(exception, "popular ${exception.localizedMessage}")
}
}
}
}
This is the actual unit test. In the mock return I am passing an exception. But when running the test I don't think the exception is thrown so the catch block is never executed.
#Test(expected = Exception::class)
fun `should not get popular search products if exception`() {
runBlockingTest {
// Arrange
val listOfEmittedResult = mutableListOf<List<CatalogProduct>>()
val job = launch {
popularSearchViewModel.listOfCatalogProductStateFlow.toList(listOfEmittedResult)
}
whenever(loadPopularSearchUseCase.execute()).thenThrow(Exception("Something bad happened"))
// Act
popularSearchViewModel.getPopularProducts()
// Assert
assertThat(listOfEmittedResult).isEmpty()
verify(loadPopularSearchUseCase).execute()
job.cancel()
}
}
I am calling Future like this:
//main_bloc.dart
...
getData() {
print("getting data");
repository.getDataFromServer().then((result) {
_handleResult(result);
}).catchError((e) {
_handleError(e);
});
}
In runtime, when there is exception from the repository, it will be catched in the catchError and forward properly.
However, when i do unit testing to that part of code like this:
//prepare
when(mockRepository.getDataFromServer()).thenThrow(PlatformException(code: "400", message: "Error", details: ""));
//act
bloc.getData();
await untilCalled(mockRepository.getDataFromServer());
//assert
verify(mockRepository.getDataFromServer());
The catchError method not called and the test is failed due to unHandled exception.
What i am doing wrong?
Your code expects to catch an error from a returned Future. Your mock throws an exception immediately (synchronously) when it is invoked; it never returns a Future.
I think that you instead would need to do:
when(repository.getDataFromServer()).thenAnswer((_) => Future.error(
PlatformException(code: "400", message: "Error", details: "")));
A simpler (and more robust) change would be to use try-catch in your code instead of Future.catchError:
Future<void> getData() async {
print("getting data");
try {
_handleResult(await repository.getDataFromServer());
} catch (e) {
_handleError(e);
}
}
I have a method that throws exception in some cases. My unit test:
class Bob extends GroovyTestCase {
void testClusterInvalidSomeParameter() {
Abc abcClass = new Abc(2, 0)
shouldFail {
abcClass.calculate()
}
}
}
If second parameter == 0, then method throws exception: "Parameter cannot be null". How can I test that it throws exactly this exception?
shouldFail() and shouldFailWithCause() returns the cause/message of the exception. If the message/cause is set then, you can use the assertion as below:
class Bob extends GroovyTestCase {
void testClusterInvalidSomeParameter() {
Abc abcClass = new Abc(2, 0)
String message = shouldFail {
abcClass.calculate()
}
assert message == "Parameter cannot be null"
}
}
A better test would be to also assert the type of Exception thrown:
String message = shouldFail( XyzException ) {
abcClass.calculate()
}
With the interface below:
public interface IRepository<T>
{
T FirstOrDefault(Func<T, bool> predicate);
}
Implemented like so:
private IRepository<Foo> Repository {get;set;}
public FooService(IRepository<Foo> repository)
{
Repository = repository;
}
public void Foo(int bar)
{
var result = Repository.FirstOrDefault(x => x.Id.Equals(bar));
if (result == null)
{
throw new Exception("Returned null, not what I expected!");
}
}
If I write a test like this:
repos = MockRepository.GenerateMock<IRepository<Foo>>(null);
repos.Expect(x => x.FirstOrDefault(y => y.Id.Equals(Arg<int>.Is.Anything))).Throw(new Exception("This exception should be thrown!"));
FooService f = new FooService(repos);
f.Foo(1);
//expecting exception to be thrown
I do not get the expected exception thrown, so I am presuming that mocked call is being ignored/not called.
However if I add IgnoreArguments() it is called and I do get the expected exception.
repos.Expect(x => x.FirstOrDefault(y => y.Id.Equals(Arg<int>.Is.Anything))).IgnoreArguments().Throw(new Exception("This exception should be thrown!"));
Any thoughts as to what it is I am doing wrong?