I am trying to test a service by using Mockito that made a remote call to external API.
If the call is fails, I should do some other operations.
SO I mock the external remote call, and I use the following:
public class Service {
private Remotecall remotecall;
public void method1() {
try {
remotecall.callAPI();
} catch (Exception e) {
logMessage("Important Log message"); // goes to another method to add somedata!
}
}
}
public class Remotecall {
public void callAPI() {
try {
callExternalAPI();
} catch (Exception e) {
throw new GenericException("some message");
}
}
}
I tried to use this way:
when(remotecall.callAPI()).thenThrow(Exception.class);
AssertTrue(logmessage);
The test return null point exception!
How can I write a test in java using Mockito to test the value in the logMessage() method.
Is it right to mock the remotecall class and inject callAPI()?
The method callAPI() takes no arguments so your 'when' statement should be
when(remotecall.callAPI()).thenThrow(Exception.class);
Related
i have the following problem:
Our java software takes incoming xml-files and parse / validate / makes some magic. Because it's a 24/7 software it's designed to resist single faults, by ignoring single files and proceeding to the next.
I want to know if there is a possible solution to test units e.g with JUnit or TestNG for already catched exceptions.
For example if have a class and function like this
public class ExceptionTest {
public static void throwEx() {
try {
int i = 1 / 0;
} catch (Exception e) {
e.printStackTrace();
}
}
}
Now i want to test if any Exception is catched. If so the test should fail. On the other hand, if i expect certain types of exceptions, the test should succeed.
public class TSTException {
#Test
public void testExceptionThrown() {
ExceptionTest.throwEx();
assert ("ExceptionsCatched.size()", 0)
}
}
I know i could edit my code to provide some kind of global variables like boolean success = true and check those but i am interested if there is another possible solution for my problem.
Thanks,
Dominik
If it is possible to modify the code You could wrap the class containing the logic and catch the exception in the wrapper class.
something like this:
public class SomeService{
public void doSomething() {
int i = 1 / 0;
}
}
public class SomeServiceCatchExceptionWrapper{
private SomeService someService;
public void doSomething() {
try {
someService.doSomething();
} catch (Exception e) {
e.printStackTrace();
}
}
}
So this way you can test both classes individually.
Our test code uses assert.
So is there any functions in assert class that can expect that a void function throws an exception?
#Test(expected=MyCustomException.class)
public void testBlahBlah_BlahBlah(){
voidMethodThatThrowsException();
}
This annotation of JUnit is what you are looking for.
Two ways I accomplish this:
First way is if I want to make sure an exception is thrown but not fail the test for it and I want to continue asserting.
try {
myObject.methodThatShouldThrowAnException("baddata");
assert.fail("Exception should have been thrown");
catch (SomeException e) { }
assert.equals(anotherMethod(), "hello");
The second way is if I don't want to do additional asserts (This is JUnit, could vary for the test framework you are using...TestNG has similar syntax):
#Test(expected = SomeException.class)
public void myTest() {
myObject.methodThatShouldThrowAnException("baddata");
}
Most testing frameworks (notably JUnit) will allow you to specify an exception class, so that the test will fail if an exception is not thrown.
If you can't use this method, then you can just wrap it in a try/catch and do the assertion in the catch block.
Ex (using JUnit):
#Test(expected=SomeException.class)
public void testSomeFunction_expectedSomeException(){
MyClass clazz = new MyClass();
clazz.someMethodThatThrowsTheException();
fail("shouldn't have gotten here...");
}
Or:
//#Test -- this annotation may or may not be supported by your framework
public void testSomeFunction_expectedSomeException(){
MyClass clazz = new MyClass();
try {
clazz.someMethodThatThrowsTheException();
fail("shouldn't have gotten here...");
}
catch (SomeException ex) {
// assert...
}
catch (Exception ex) {
fail("Some other exception occurred, also not good");
}
}
I have two methods at service layer in springs MVC. In one method i am throwing ObjectNotFoundExcetion with my own reason when my record not found. I am calling this method from the first method. In first method I have declared try catch for it and have further code. But once i get the ObjectNotFoundException, the whole transaction rolls back. Hence I am not able to do further processing. Why is the transaction rolling back at service layer ?
public void foo() {
try {
boo();
} catch(ObjectNotFoundException e) {
}
// further code.
}
public void boo() throws ObjectNotFoundException
{
if () {
} else {
throw new ObjectNotFoundException("Record not found");
}
}
I've made an MethodRule and #Rule-annotation to make my test-life a bit easier.
It checks if a specific exception had been thrown and checks if the exception-message equals or contains the given message.
Now when i run a testmethod with more lines to test, it only takes the first line and than is ready. How do I make so all my lines in the testmethod are tested?
This is my code:
Annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD})
public #interface ExpectedDomeinValidatieMessage {
String value() default "";
String contains() default "";
}
MethodRule:
#Override
public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
ExpectedDomeinValidatieMessage message = method.getAnnotation(ExpectedDomeinValidatieMessage.class);
if (message == null) {
base.evaluate();
} else {
try {
base.evaluate();
Assert.fail("DomeinValidatieException not thrown");
} catch (DomeinValidatieException e) {
if (StringUtils.isNotBlank(message.value())) {
if (!e.getMessage().equals(message.value())) {
throwException(e, "", message.value(), e.getMessage());
}
}
if (StringUtils.isNotBlank(message.contains())) {
if (!e.getMessage().contains(message.contains())) {
throwException(e, "Segment niet gevonden:", message.contains(), e.getMessage());
}
}
}
}
}
private void throwException(Throwable exception, String message, String expected, String actual) {
ComparisonFailure cf = new ComparisonFailure(message, expected, actual);
cf.setStackTrace(exception.getStackTrace());
throw cf;
}
};
Usage:
#Test
#ExpectedDomeinValidatieMessage("[Werkzaamheden] WerkzaamMetGevaarlijkeStoffen niet gevuld")
public void valideerWerkzaamMetGevaarlijkeStoffen() throws DomeinValidatieException {
aanvraag.getVerzekerde().getWerkzaamheden().setWerkzaamMetGevaarlijkeStoffen(null);
validator.valideer();
}
If I use it like this, it only tests the first test in the method:
#Test
#ExpectedDomeinValidatieMessage("[Werkzaamheden] WerkzaamMetGevaarlijkeStoffen niet gevuld")
public void valideerWerkzaamMetGevaarlijkeStoffen() throws DomeinValidatieException {
aanvraag.getVerzekerde().getWerkzaamheden().setWerkzaamMetGevaarlijkeStoffen(null);
validator.valideer(); //Only this one is tested
aanvraag.getVerzekerde().getWerkzaamheden().setWerkzaamMetGevaarlijkeStoffen("bla");
validator.valideer(); //This is NOT tested
}
Run the code through a debugger. My guess is that the first call to valideer() does indeed throw an exception even though you don't expect it.
The JUnit assertXXX methods work by throwing exceptions (specifically AssertionError). So when an exception is thrown (either by your code, or by an assert) control exits from the test method. There isn't any way to restart from the place where the exception is thrown.
You probably want Parameterized, which allows you to run the same tests multiple times with different parameters.
EDIT: I suspect that valideer() is throwing an Exception. To explain a bit further, let's paraphrase your code. When you define a rule, what you're effectively doing is the following:
try {
base.evaluate(); // this calls valideerWerkzaamMetGevaarlijkeStoffen()
Assert.fail("DomeinValidatieException not thrown");
} catch (DomeinValidatieException e) {
// evaluate whether or not the test has failed or not
}
This means that if your first call to valideer() throws an Exception, then control is transferred to the catch block above. There isn't a chance to continue executing the test, because the control has passed elsewhere. You can pass/fail the test as much as you like, but control has passed to the catch block above.
By the way, MethodRule has been deprecated in the later versions, you should be using TestRule instead.
I have some unit tests which exercise code which makes calls out to a test server, in order to make sure that the requests are well-formed (i.e. we get valid data back in response). However, this means that the unit tests, and hence the build, can get blocked if this test server is down. This does not conform to good unit test practices, but as a thought experiment let's say I'm not allowed to delete these tests or change them so they don't actually call out to the server. I want to change them so that they will still pass if the server is down (i.e. trying to connect results in ConnectException), but fail if any other exception occurs. Making it more difficult, the code under test doesn't throw the ConnecException directly, but throws a wrapper exception that contains it. So initially, that means each test will go from looking like this:
#Test
public void testNumberOne() {
// body of test...
}
To this:
#Test
public void testNumberOne() {
try {
// body of test...
} catch (ThirdPartyWrapperException e) {
if (!(e.getRootCause() instanceof ConnectException) {
throw e;
}
}
}
Is there any way I can avoid having to paste that try/catch into each unit test?
I know I can refactor out at least some of it, ala:
#Test
public void testNumberOne() {
try {
// body of test...
} catch (ThirdPartyWrapperException e) {
handleException(e);
}
}
private void handleException(ThirdPartyWrapperException e)
throws ThirdPartyWrapperException {
if (!(e.getRootCause() instanceof ConnectException) {
throw e;
}
}
But is there anything further I can do?
I would add a line to the start to determine if the required resources are available
#Test
public void testNumberOne() {
if (!requiredServerAvailable()) return;