I need to test the Exception but it gets the following error.
org.testng.TestException:
Method ContactIdentifierHelperTest.test()
[pri:0, instance:se.cambio.contactadministration.contact.helper.ContactIdentifierHelperTest#6d7b4f4c]
should have thrown an exception of type class SpiderException
Test method:
#Test(expectedExceptions = { SpiderException.class })
public void test() {
ContactData contactData = getContactData();
contactIdentifierHelper.getSpellId(contactData);
}
Method tested:
public String getSpellId(final ContactData contactData)
{
String s = null;
try
{
s = someMethod();
}
catch (SpiderException e)
{
e.printStackTrace();
}
return s;
}
Where have I gone wrong in this?
The expected behavior is that your method throws an Exception and your test fails, but it cannot never be successful (and this is correct), because you catch the exception in the body of your method.
In order to throw the exception you can simply have:
public String getSpellId(final ContactData contactData) throws SpiderException
{
return someMethod();
}
However, keep in mind that your test will be successful only if someMethod() effectively throws an exception!
Now, let me make a remark: this test does not have any sense: you are testing getSpellId but your buisiness logic is inside someMethod, and furthemore, getSpellId accept a parameter that is never used in the body ...
I suggest you change the way you think about this.
You need a repeatable, predictable way for your tested method to thrown an exception. One way to achieve that is via certain inputs.
Imagine your method looks something like this:
public String getSpellId(final ContactData contactData) throws SpiderException
{
if ( contactData == null ) throw new ArgumentException("input is null")
//some other code
}
this is something repeatable, you can always trigger the exception by passing null. You know how your code should behave, there is no uncertainty and you can test for this behaviour.
What you have however is another method call, which might fail, but you don't know how and why. This is a big no, when it comes to unit testing.
You might be better served by adding an exception test for your other method and not bother with this one.
What you really want to avoid is for your test to have too much knowledge of the code under test. You don't want to have to go through who knows how many layers in order to achieve what you want, because this leaves you with brittle tests which will need to change every time a code change happens.
So, change the way you think about the code and aim to make it testable.
Also, if you want to test for an exception, you must make sure you don't catch that exception as this will hide the actual thing.
Related
I am getting following exception while running the tests. I am using Mockito for mocking. The hints mentioned by Mockito library are not helping.
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
Here is my method:
From ps.setString I am unable to do code coverage. Can anyone help me?
public class Dao{
public int[][] batchInsertAll(Collection<UploadRequest> request, int batchSize, final String jobId) {
int[][] updateAllCounts = jdbcTemplate.batchUpdate("insert into tb_import(id,name) values("","")", request, batchSize,
new ParameterizedPreparedStatementSetter<UploadRequest>() {
public void setValues(PreparedStatement ps, UploadRequest argument) throws SQLException {
ps.setString(1, Id);
ps.setString(2, argument.getName());
}}); return updateAllCounts
}
}
Here is my test code:
#Test
public void batchInsertAll() {
int batchSize = 1000;
String jobId = "xyz";
List<UploadRequest> fileData = new ArrayList<UploadRequest>();
UploadRequest rowdata1 = new UploadRequest("1", "xyz");
UploadRequest rowdata1 = new UploadRequest("1", "abc");
fileData.add(rowdata1);
fileData.add(rowdata2);
int[][] updateAllCounts = new int[][] { { 1, 2 }, { 3, 4 } };
try {
Mockito.doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) {
PreparedStatement ps = Mockito.mock(PreparedStatement.class);
ParameterizedPreparedStatementSetter bpss = invocation.getArgumentAt(1,
ParameterizedPreparedStatementSetter.class);
try {
bpss.setValues(ps, 1);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return updateAllCounts;
}
}).when(jdbcTemplate).batchUpdate(anyString(), fileData, 1000,
any(ParameterizedPreparedStatementSetter.class));
} catch (Exception e) {
assert (true);
}
mockDao.batchInsertAll(fileData, 1000, jobId);
}
First you have to think - what is your goal here?
You wrote a class Dao and a method batchInsertAll. I would think you'd want to test that. If you want to test that though you need to actually call that method. Calling
mockDao.batchInsertAll(fileData, 1000, jobId);
makes it look, like you're just calling a mock you created to test it, which obviously will do nothing except do whatever you configured that mock to do.
Also, the catching of Exception with assert(true) will not do what you think it'll do - this is a base Java assertion used for sanity checks in non-production builds. It will either not be run at all (as might be default behaviour when running an application without appropriate flag to enable them) or do nothing (since true is true, so it passes). It will not end the test with a positive result, it will not tell you it happened, it doesn't even count as test assertion. You might want to add some logging there, as without knowing an exception you didn't expect was thrown any number of shenanigans can slip by. Or even better, don't catch exceptions in tests. If unexpected exceptions get thrown you want the test to fail anyway right?
As to your direct problem it's hard to tell for sure without seeing the entire test class (I can see three mocks in your code - jdbcTemplate, mockDao and ps, only one of which is initialized as a Mock in the code you've given us, you only stub jdbcTemplate and from what I can tell without running the code it looks correct). Either the problem is somewhere you haven't shown us, or exception is thrown during stubbing of jdbcTemplate, causing that to not finish and fail leaving mock in invalid state.
Also worth noting, most of your code in doAnswer method is irrelevant. Even if you call real batchInsertAll that in turn will call jdbcTemplate.batchUpdate with some parameters, and your mock will return updateAllCounts array. doAnswer() line of methods is useful only if you need to change what your mock returns based on input arguments, otherwise you do some useless calculations you could have done wrong and end up with same result as .thenReturn(updateAllCounts) would.
In below code a checked exception is being thrown by ClassToTest.throwsException(). My preference is to add throws exception to the JUnit method signature instead of wrapping the code that throws an exception in a try catch. This preference is just based on the fact that I think its neater. Is there a coding convention I'm breaking here? Is there a difference in functionality from a testing point of view in throwing the exception versus try/catch in the testing method?
import org.junit.Test;
public class TestingClass {
#Test
public void getDataTest() throws Exception {
new ClassToTest().throwsException();
}
}
versus :
import org.junit.Test;
public class TestingClass {
#Test
public void getDataTest() {
try {
new ClassToTest().throwsException();
} catch (Exception e) {
e.printStackTrace();
}
}
}
ClassToTest.java :
public class ClassToTest {
public void throwsException() throws Exception {
}
}
If one does not expect an Exception to be thrown, there is no added benefit in adding a try-catch block to the code. Even worse, only adding a try-catch block will lead to the test passing. To make the test fail, one would have to add a call to fail() to make the test actually fail. This is a possible source for error (if one forgets to call fail()).
For completeness sake, I will talk shortly about how to verify that a certain Exception has been thrown. There are three approaches that come to my mind.
In the first attempt, one could use try-catch, but with an added fail() in the try-block, just after the calls that should throw the expected Exception. In the catch-block, one would then catch the expected Exception. All other Exceptions would be re-thrown and thus the test would fail. This has the same downsides as its sibling mentioned above.
Second, there is the JUnit4 way by annotating the test itself with #Test(expected = ExpectedException.class). This seems neat at first, but breaks the Given-When-Then structure of tests, often leading to tests looking like this:
#Test(expected = ArrayIndexOutOfBoundsException.class)
public void test() {
// GIVEN
final int[] array = new int[10];
// WHEN
final int value = array[10];
// THEN: an ArrayIndexOutOfBoundsException should be thrown
}
which is okay-ish.
Lastly, there is the JUnit5 way by wrapping the actual call into a call of assertThrows(...):
#Test(expected = ArrayIndexOutOfBoundsException.class)
void test() {
// GIVEN
final int[] array = new int[10];
// WHEN
final Exception e = assertThrows(ArrayIndexOutOfBoundsException.class,
() -> {
int value = array[10];
}
);
// THEN
assertTrue(e.getMessage().contains("10"));
}
While this still does not properly separates the WHEN from the THEN (I think this is not possible in Java), it gives the added benefit to allow checking specific parts of the Exception, e.g. the message1.
I would suggest this article over at Baelung as a further read.
1This is also possible in JUnit4, but is either done through an explicit try-catch block or through a very cumbersome mechanism that definitively breaks the Given-When-Then structure. For more information, please check the article over at Baelung mentioned above.
Simply add the throws clause to the method declaration and let the exception bubble up, as written in the JUnit4 FAQ - How do I write a test that fails when an unexpected exception is thrown?:
Declare the exception in the throws clause of the test method and don't catch the exception within the test method. Uncaught exceptions will cause the test to fail with an error.
The following is an example test that fails when the IndexOutOfBoundsException is raised:
#Test
public void testIndexOutOfBoundsExceptionNotRaised()
throws IndexOutOfBoundsException {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
IndexOutOfBoundsException might not be a good example here, since it is a RuntimeException, but the approach is the same for other exceptions.
I have a method which under certain conditions may throw an exception, but most of the time will not. I would like to require anyone who calls this method to catch the exception if they call it under the "dangerous" conditions, but not have to worry about it under "safe" conditions.
public static boolean dangerousSituation; // set somewhere else
public sometimesDangerousMethod() throws MyException {
// some code
// may throw MyException if dangerousSituation == true
// will never throw MyException if dangerousSituation == false
}
otherMethod() {
dangerousSituation = false;
sometimesDangerousMethod(); // shouldn't have to worry about MyException
// if it can't possibly happen
dangerousSituation = true;
try {
sometimesDangerousMethod(); // should be required to handle
// MyException if it may possibly happen
} catch(MyException e) {
// handle MyException
}
}
That is, I would like to require a try/catch block around sometimesDangerousMethod() if and only if dangerousSituation == true.
The reason I want this is because I don't want to bother developers with exception handling if they stick to safe situations anyway. But of course, if a developer does use a dangerous situation, the compiler should let him know.
Is there some way to get this behavior in Java?
I have considered breaking up sometimesDangerousMethod() into two methods: one dangerous, one safe. But I don't think this makes sense since this would require developers to be aware of two methods which do basically the same thing.
The functionality you're looking for doesn't exist. You can either split it into two methods, or your coworkers will have to use a try-catch. Sorry, but sometimes the answer is just "No".
#mypetlion is accurate on the most part.
There are a couple of other options for you to consider is:
Would it be possible to handle the exception inside of sometimesDangerousMethod() instead of otherMethod()? If so, then you could pass in the logging/metric object to the method, try/catch inside of the method, and log an error message or update a metric when this occurs. This way, you don't have to worry about try/catch in the case that the exception doesn't occur.
You could break it up into 2 methods like #mypetlion mentioned and with a bit of organization, it may be good enough code:
`
public class Solution {
public static boolean dangerousSituation; // set somewhere else
public void notDangerousMethod(){
// will never throw MyException
}
public void dangerousMethod() throws MyException {
// throws MyException
}
public void sometimesDangerousMethod() throws MyException {
if(dangerousSituation){
dangerousMethod();
} else {
notDangerousMethod();
}
}
public void otherMethod() {
dangerousSituation = false;
// Option 1:
if(dangerousSituation){
try{
dangerousMethod();
} catch(MyException e) {
// handle MyException
}
} else {
notDangerousMethod();
}
// Option 2:
try {
sometimesDangerousMethod(); // should be required to handle
// MyException if it may possibly happen
} catch(MyException e) {
// handle MyException
}
}
`
Depending on contents of sometimesDangerousMethod(), this may be overkill. If it is a few very simple lines of logic, it might be worth it to implement your original design. I don't think the developers would mind :)
You're missing the point of the word Exception. Your code should not throw an Exception unless there is an exceptional situation. Properly designed code that consumes your code still needs to handle the possibility of an exceptional situation.
You shouldn't worry so much about the users of your method having to worry about exceptions.
If your method can fail for whatever reason, it should declare the exception (or use an unchecked exception) and throw the exception if it really fails. That's exactly what exceptions are for.
So I think dangerousSituation is in fact a very dangerous flag. In the code you propose, setting the flag translates to "do not tell me if the method fails [because I know better than the method's implementation that there will not be a failure]".
So, the only reason for not throwing can be a method that will surely succeed. And any decent Java developer should know how to handle exceptions (typically by letting them pass through to a top level where all exceptions are caught and logged).
I'm new to Java & its design patterns, I have a scenario like this:
Method 1 calls Method 2.
Method 2 looks like the following:
public String createUser(String username, String password) {
someApi.do(config -> {
//code here with respect to someApi.
});
}
now the trick is I need to return the value to caller which is method 1. If there are no exceptions then that is fine. However the code block inside do can throw exception, which will be handled in a separate listener class like this:
public class TestListener implements SomeApiListener {
#Override
public void exception(Throwable cause) {
}
}
Now how should I send back the exception to method 1 from this listener? I'm really confused.
it's not clear what that API do, where the listener is assigned, and what other methods it has, like if there is also onSuccess() ?
what i got from this, is that, you are dealing with async call, which usually do not return a value directly, it deals with a CallBack which in your case is SomeApiListener
So, ... I would make createUser() receives extra arg, SomeApiListener, pass the listener as anonymous inner class (with implementation) when calling the method (from caller).
ex,
public String createUser(String username, String password, SomeApiListener listener) {
someApi.do(config -> {
//code here with respect to someApi.
//somewhere here you are creating a TestListener ?,
//well... don't, and use the one passed from caller (listener)
});
}
Caller part will look like this:
public void method1(){
//..some code ...
createUser(username, password, new SomeApiListener(){
#Override
public void exception(Throwable cause) {
//handle exception...
}
#Override
public void success(Response response) {
//handle response ...
}
});
}
Note: you can still pass TetstListern, if you want, in that case you will have to have a physical class (local class) defined and instantiated, the anonymous-inner-class is somehow a shortcut for that, you don't create a local class, just pass it as an arg.
You can't, at least not in any simple way. I'd expect the documentation for your someApi to demonstrate some common use cases, with exception handling included. If you're combining different ways of programming ("normal" java & functional programming), you can get into tricky situations.
Based on the information you've given, a clumsy solution could look something like this (code obviously not fit for compilation):
public class MyClass implements SomeApiListener {
private Throwable e;
public void exception(Throwable cause) {
e = cause;
}
public void method1() {
createUser("foo", "bar");
if(e != null) {
// Exception was thrown, do something with it
}
}
}
However this is in no way a recommendation. It's clumsy, hacky and bad in every way. A better solution would involve not trying to send the exception back to method1, but instead to modify your code to work in the way that someApi expects.
It depends on your design on how to handle exceptions. Normally, if the method 2 is an utility method then throw the exception back to method 1 and let it handle the exception. Else, if method 2 understands the use case for which it is called then handle the exception there. There are no hard and fast rules, but keep the utility classes clean and send the exception back to the caller so that caller can handle it.
I cannot run my test because the test gets red squiggly error line in this statement decorator.decorate(new EncoderColumnDecorator()) requiring me to use either try/catch or add throws.
This is the error message.
Why do I have to put either try/catch or throws exception when I already have an attribute "expected"
My unit test:
#Test(expected=DecoratorException.class)
public void testDecorate_exception() {
decorator.decorate(new EncoderColumnDecorator()); -----Error in this line
}
Method under test
#Override
public String decorate(Object arg0) throws DecoratorException {
try{
//some code
}
}catch(Exception e){
throw new DecoratorException();
}
return arg0;
}
}
That is simply the rule that has to be followed for the code to be valid Java. If a function calls another function that throws then it must either also throw that exception or it must catch it.
It is a bit like static typing of variables. While it may seem inconvenient it can help ensure correct code by not allowing ambiguity. Having the compiler report any inconsistency helps with detecting problems much earlier.