Catch Exception A Throw Exception B - Coverage Junit5 - junit5

Iam catch FeignException, but im throws FeingClientException(customized exception).
Sonar says that this FeingClientExceptionis not coveraged by junit test.
Any idea to cover it.
My exception is like this:
public class FeignClientException extends RuntimeException {
public FeignClientException(FeignException ex, ErrorMessageEnum errorMessageEnum, ContextExceptionEnum contextExceptionEnum, String cpf) {
throwException(ex, contextExceptionEnum, errorMessageEnum, cpf);
}
private void throwException(FeignException ex, ContextExceptionEnum contextExceptionEnum, ErrorMessageEnum errorMessageEnum, String cpf) {
if (ex.status() == HttpStatus.NOT_FOUND.value() || ex instanceof FeignException.NotFound) {
throw new FeignClientNotFoundException(
errorMessageEnum != null ? errorMessageEnum.msgUserFormatted(cpf) : ErrorMessageEnum.REGISTRO_NAO_ENCONTRADO.msgUserFormatted(cpf),
errorMessageEnum != null ? errorMessageEnum.msgDeveloper() : ErrorMessageEnum.REGISTRO_NAO_ENCONTRADO.msgDeveloper(),
String.valueOf(HttpStatus.NOT_FOUND.value()),
contextExceptionEnum.value());
}
if (ex.status() == HttpStatus.SERVICE_UNAVAILABLE.value() || ex instanceof RetryableException) {
throw new ServicoForaDoArException(
ErrorMessageEnum.SERVICO_FORA_AR.msgUserFormatted(contextExceptionEnum.value()),
ErrorMessageEnum.SERVICO_FORA_AR.msgDeveloper(),
String.valueOf(HttpStatus.SERVICE_UNAVAILABLE.value()),
contextExceptionEnum.value());
}
if (ex.status() == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
throw new FeignClientInternalServerErrorException(
ErrorMessageEnum.SERVICO_RETORNOU_ERRO.msgUserFormatted(contextExceptionEnum.value()),
ErrorMessageEnum.SERVICO_RETORNOU_ERRO.msgDeveloper(),
String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()),
contextExceptionEnum.value());
}
throw new FeignBadGatewayException (
ErrorMessageEnum.SERVICO_RETORNOU_ERRO.msgUserFormatted(contextExceptionEnum.value()),
ErrorMessageEnum.SERVICO_RETORNOU_ERRO.msgDeveloper(),
String.valueOf(HttpStatus.BAD_GATEWAY.value()),
contextExceptionEnum.value());
}
}
My test is:
void test2() {
doThrow(FeignException.NotFound.class).when(preAprovadoClient).consultaPreAprovadoCDC(Mockito.anyString(), Mockito.anyString());
assertThrows(FeignClientException.FeignClientNotFoundException.class, () ->{
PreAprovado preAprovado = preAprovadoGateway.consultarPreAprovadoCDC("01234567890");
});
}

I think you're mocking the wrong method. You're calling the method consultarPreAprovadoCDC with one parameter, but you have mocked it with two String parameters, maybe that is causing this confusion.
Try to either changing the call to use two String parameters or mock the method with only one anyString() as parameter.

Related

mockk every {}.throws() Exception fails test

I need to verify that a certain call is not made, when a previous method call throws an Exception.
// GIVEN
every { relaxedMock.eats() }.throws(NotHungryException())
// WHEN
sut.live()
// THEN
verify (exactly = 0) { relaxedMock2.sleeps() }
Problem with this code, it fails because of the Exception thrown and not because of the failed verification.
I understand that your WHEN block will always throw an exception.
In that case you have multiple options from my point of view:
Simple plain Kotlin. Wrap the WHEN block with a try-catch block, e.g. like this:
// GIVEN
every { relaxedMock.eats() }.throws(NotHungryException())
// WHEN
var exceptionThrown: Boolean = false
try {
sut.live()
} catch(exception: NotHungryException) {
// Maybe put some assertions on the exception here.
exceptionThrown = true
}
assertTrue(exceptionThrown)
// THEN
verify (exactly = 0) { relaxedMock2.sleeps() }
For a bit nicer code, you can use JUnit5 API's Assertions. assertThrows will expect an exception being thrown by a specific piece of code. It will fail the test, if no exception is thrown. Also it will return the thrown exception, for you to inspect it.
import org.junit.jupiter.api.Assertions
// GIVEN
every { relaxedMock.eats() }.throws(NotHungryException())
// WHEN
val exception = Assertions.assertThrows(NotHungryException::class.java) { sut.live() }
// THEN
verify (exactly = 0) { relaxedMock2.sleeps() }
If you're using Kotest you can use the shouldThrow assertion. Which also allows you to retrieve the thrown exception and validate its type.
import io.kotest.assertions.throwables.shouldThrow
// GIVEN
every { relaxedMock.eats() }.throws(NotHungryException())
// WHEN
val exception = shouldThrow<NotHungryException> { sut.live() }
// THEN
verify (exactly = 0) { relaxedMock2.sleeps() }
I had similar issue and found that my method is not surrounded by try catch. This mean the method will always throw exception.
Test
The unit test to verify the result when the following method is called while stubbing it with predefine Exception
#Test
fun returnSearchError() {
every { searchService.search(query) }.throws(BadSearchException())
val result = searchRepository.search(query)
assertEquals(SearchStates.SearchError, result)
}
Faulty code
fun search(query: String): SearchStates {
val result = searchService.search(query) // No try catch for the thrown exception
return try {
SearchStates.MatchingResult(result)
} catch (badSearchException: BadSearchException) {
SearchStates.SearchError
}
}
Refactored it to
fun search(query: String): SearchStates {
return try {
val result = searchService.search(query)
SearchStates.MatchingResult(result)
} catch (badSearchException: BadSearchException) {
SearchStates.SearchError
}
}

Do an action when an error occurs RxJava

I need to create a folder when it doesn't exist. In my case, the only way to do so is to capture the error and handle it to create the folder wanted.
But all i can find is
public static Observable<Boolean> folderExists(final Context context, final String targetPath, final String currentpath) {
Application application = Application.get(context);
//i browse the folder to get all the items
return browseFolderObservable(context,currentpath)
.subscribeOn(application.defaultSubscribeScheduler())
.doOnError(new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
BsSdkLog.d("Error no file found");
}
})
.map(new Func1<ArrayList<Item>, Boolean>() {
#Override
public Boolean call(ArrayList<Item> items) {
if(items.isEmpty()) {
BsSdkLog.d(" No items");
return false;
}else {
for(int i=0;i<items.size();i++)
{
Item item=items.get(i);
BsSdkLog.d(item.toString());
}
BsSdkLog.d("Right-here");
return true;
}
}
});
}
I want to call the method that i have that creates the folder when the error occurs but i don't know how to do that.
I'm new to this so i'd really appreciate the help
Thanks
The basic principe looks like this. I used the Java NIO library for testing.
The method 'createFolder' just wraps creating a folder. The test 'name' invokes the Single and checks for an Exception. If it is an IOException it will return a fallback value. You may do something different in there. You just provide a fallback single. If it is an error different from IOException, it will return the error.
#Test
void name() throws Exception {
final String TO_CREATE = "/home/sergej/Downloads/Wurstbrot";
this.createFolder(TO_CREATE)
.onErrorResumeNext(throwable -> { // handle Exception:
// Validate Exception
if (throwable instanceof IOException) {
// Return fallback
return Single.just(Paths.get("/home/sergej/Downloads/"));
}
return Single.error(throwable);
})
.test()
.await()
.assertValueCount(1)
.assertValue(path -> path.endsWith(TO_CREATE))
.assertNoErrors();
}
private Single<Path> createFolder(String p) {
return Single.defer(() -> { // may throw some IOException
Path path = Paths.get(p);
if (!Files.exists(path)) {
Path createdDirectory = Files.createDirectory(path); // will throw if already exists
return Single.just(createdDirectory);
}
// Or just return Path, because it already exists???
return Single.error(new IOException("Already exists"));
});
}

how to return something from a Ninject Interceptor

I have written a common validator as part of Ninject interceptor. My requirement is that I have to return a response object, just like how any service method in my project returns, for consistency sake. By returning a response object also helps me to send back an appropriate validation message when the validator fails. How do I do that in the interceptor? I understood that the Intercept() returns nothing. I tried throwing an exception but I don't know where to catch it. Can someone help me?
public void Intercept(IInvocation invocation)
{
var validationFails = false;
if (validationFails)
{
// return an object
// response.ErrorMessage = "Validation Error"
// Or throw exception, but where should I catch it
throw new Exception(statusMessage);
}
else
{
invocation.Proceed();
}
}
Assign the ReturnValue and don't call Proceed when validation fails.
public class MyRequestHandler
{
Response ProcessRequest(string input) { return new Response(); }
}
public MyValidationInterceptor : IInterceptor
{
public void Intercept( IInvocation invocation )
{
if (NeedsValidation(invocation.Method) &&
!IsValidRequest((string)invocation.Arguments[0]))
{
invocation.ReturnValue =
new Response { ErrorMessage = "Validation Error" };
return;
}
invocation.Proceed();
}
}
I had to hook up my interceptor to business layer methods, instead of service methods, and am able to return proper return value as part of my response.

How to generalize a JMockit test using Spring autowiring

So I would like to use a generic test for a few different Dao methods. Inside the Dao, I implemented the save functionality to be Entity independent, so I figured it would be best to make the tests Entity independent as well. Currently I have the following for one of my jmockit tests that is autowired with spring.
#Injectable
public EntityManager em;
#Tested
SyncClaimDao syncClaimDao = new SyncClaimDaoImpl();
#Before
public void setUp() {
Deencapsulation.setField(syncClaimDao, "em", em);
}
private void testSaveEntity (Class T) {
// Existing claim happy path
new Expectations() {
{
em.contains(any); result = true;
em.merge(any);
}
};
if (T.isInstance(SyncClaimEntity.class)) {
Assert.assertTrue(syncClaimDao.saveClaim(new SyncClaimEntity()));
} else if (...) {...}
}
#Test
public void testSaveClaim() {
testSaveEntity(SyncClaimEntity.class);
}
SyncClaimDaoImpl
#Override
public boolean saveClaim(SyncClaimEntity claim) {
return saveEntity(claim);
}
private boolean saveEntity(Object entity) {
boolean isPersisted = false;
try {
isPersisted = em.contains(entity);
if (isPersisted) {
em.merge(entity);
} else {
em.persist(entity);
em.flush();
isPersisted = true;
}
logger.debug("Persisting " + entity.getClass().getSimpleName() + ": " + entity.toString());
}
catch (NullPointerException ex) {
...
}
catch (IllegalArgumentException ex) {
...
}
return isPersisted;
}
When I run the tests I am seeing the following errors:
mockit.internal.MissingInvocation: Missing invocation of:
javax.persistence.EntityManager#contains(Object)
with arguments: any Object
on mock instance: javax.persistence.$Impl_EntityManager#44022631
at at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
... 4 more
Caused by: Missing invocation
at [redacted].dal.dao.SyncClaimDaoImplTest$1.<init>(SyncClaimDaoImplTest.java:48)
at [redacted].dal.dao.SyncClaimDaoImplTest.testSaveEntity(SyncClaimDaoImplTest.java:46)
at [redacted].dal.dao.SyncClaimDaoImplTest.testSaveClaim(SyncClaimDaoImplTest.java:67)
... 10 more
Now if I just move the Expectations block into the #Test method like so:
#Test
public void testSaveClaim() {
new Expectations() {
{
em.contains(any); result = true;
em.merge(any);
}
};
Assert.assertTrue(syncClaimDao.saveClaim(new SyncClaimEntity()));
I get a successful test run as should be. I'm thinking that the spring autowiring for the Test method is not properly scoping my Expectations. That's why I'm seeing the missing invocation errors.
Does anyone have any ideas on how to generalize my Expectations so I can create simpler tests for generalized methods?
I see the mistake now: T.isInstance(SyncClaimEntity.class). The Class#isInstance(Object) method is supposed to be called with an instance of the class, not with the class itself; so, it's always returning false because SyncClaimEntity.class is obviously not an instance of SyncClaimEntity.

How do I factor out my use of `try {...} catch (Error e) {log_error(e);}`

I need errors to be logged in the same way across a large number of function calls. Here I want errors from foo.create(...) and File.new_tmp(...) to be logged by handle_error(...).
// compile with `valac --pkg gio-2.0 main.vala`
void log_error(Error e) {
// error logging here
}
void main() {
var foo = File.new_for_path("foo");
try {
foo.create(FileCreateFlags.NONE);
} catch (Error e) {
log_error(e);
}
FileIOStream tmp_stream;
try {
File.new_tmp(null, out tmp_stream);
} catch (Error e) {
log_error(e);
}
}
(Yes, main should continue with the FileIOStream stuff if foo.create fails, which is why they're in separate try/catch blocks.)
I want to factor out the use of try {...} catch (Error e) {log_error(e);} into a function like so:
delegate void Action();
void log_error(global::Action action) {
try {
action();
} catch (Error e) {
// error logging here
}
}
void main() {
var foo = File.new_for_path("foo");
log_error(() => foo.create(FileCreateFlags.NONE));
FileIOStream tmp_stream;
log_error(() => File.new_tmp(null, out tmp_stream));
}
But valac gives the warning unhandled error 'GLib.IOError' because you can't seem to catch errors thrown within a closure, nor can I just rewrite log_error(...) as a #define macro as vala doesn't support them. So what can I do?
You can catch exceptions thrown in closures, you just need to have the delegate throw the exception. What you want is probably something like this:
public delegate T? Action<T> () throws GLib.Error;
T? log_error<T> (global::Action<T> func) {
try {
return func ();
} catch (GLib.Error e) {
// error logging here
return null;
}
}
void main () {
var foo = File.new_for_path("foo");
log_error<GLib.FileOutputStream> (() => foo.create (FileCreateFlags.NONE));
FileIOStream? tmp_stream = null;
GLib.File? f = log_error<GLib.File> (() => File.new_tmp (null, out tmp_stream));
}
Note that I've made it a generic so you can actually use a return value. If you want it should be trivial to remove the generic type argument and just return void, though you'll lose some flexivility.