JUnit exception test fails (unexpectedly) - java

I'm trying to run a JUnit test to test a method that will throw an exception. However, the test fails and I have no clue as to why it fails. The method that throws the exception is: calcultor.setN( );. I made two versions of this test, both of them fail even though they should pass.
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void testSetNZero() {
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Het aantal CPU's is minder dan 1");
Amdahl calculator = new Amdahl();
calculator.setN(0);
fail("Exception not thrown");
}
#Test (expected = IllegalArgumentException.class)
public void testSetNZero() {
Amdahl calculator = new Amdahl();
calculator.setN(0);
}
Amdahl class:
public class Amdahl
{
private int N;
public void setN (int n) {
if(n < 1) throw new IllegalArgumentException ("Het aantal CPU's is minder dan 1");
this.N = n;
}
}

testSetNZero fails because:
#Test (expected = IllegalArgumentException.class)
public void testSetNZero() {
and
#Rule
public ExpectedException exception = ExpectedException.none();
contradict each other and define a test that will always fail (it must both throw an exception and also not in order to pass). Use either ExpectedException or #Test(expected = ...).

I have solved my issue by using try-catch blocks whenever I expected an exception. If no exception or the wrong exception was present, the test fails.
#Test
public void testSetNZero() {
Amdahl calculator = new Amdahl();
try{
calculator.setN(0);
fail();
} catch(IllegalArgumentException e){}
}

Related

Testing method with many exception on

Hello i have 30 exception that are thrown by 30 values I pass to my test on the same method which takes the input,but it seems I cannot put the exception in the catch block,is there any workaround?
#DataProvider
public Object[][] providedInfo()
{
return new Object[][]
{
{MyGuests1.class,SQLException.class} //and many more
};
}
#Test(dataProvider="providedInfo")
public void f(Class c , Throwable ex) {
ItemsRepository x =new ItemsRepository();
try{
x.findAll(c);
}
catch(Throwable ex)
{
}
You can use the https://junit.org/junit4/javadoc/4.12/org/junit/rules/ExpectedException.html rule.
#Rule
public ExpectedException thrown= ExpectedException.none();
#DataProvider
public Object[][] providedInfo()
{
return new Object[][]
{
{MyGuests1.class,SQLException.class} //and many more
};
}
#Test(dataProvider="providedInfo")
public void f(Class c , Throwable ex) {
thrown.expect(ex);
ItemsRepository x =new ItemsRepository();
x.findAll(c);
}
If there throw is as expected the test case will fail. There is also some more verbose testing options with it.
Additionally you may want to look into assertJ if you are using Java 8 or greater as it has some additional measures for excption testing which may help, but I generally find their API better.

Method under test calling private void method which I'd also like to include in my test

I've a JUnit which I want to use to test for exceptions. It's like this:
#Test
public void test1() throws Exception {
boolean testPass;
try {
method1();
testPass = true;
Assert.assertTrue(testPass);
}
catch(Exception e) {
testPass = false;
Assert.assertTrue(testPass);
}
System.out.println("End of test2 Junit");
}
method1() is like this:
public void method1() throws Exception {
try {
do something....
method2();
} catch (Exception e) {
throw e;
} finally {
do some more...
}
}
For what I want, my test is fine when just considering method1(). My problem is that method2() is called by method1() and can also throw an exception. It's like this:
private void method2() throws Exception {
if (confition is not met) {
do something...
throw new Exception();
} else {
do something else;
}
}
It's possible that no exception is thrown by method1() but then gets thrown by method2(). I'd like my test to check for an exception from either but I'm not sure how to factor method2() into my test, especially as it's a private void method. Can this be done and if so, how?
According to your code it is possible only if you can achieve true condition in this if:
if (condition is not met) {
do something...
throw new Exception();
} else {
do something else;
}
If for some reasons you couldn't prepare such kind of condition in the unit tests (say, Internet connection is needed) you may extract the condition checking into new method:
if (isNotCondition()) {
do something...
throw new Exception();
In the test class you override new method and return what you want:
MyService myService = new MyService() {
#Override
boolean isNotCondition() {
return true;
}
}
This is more compact way to test exceptional cases:
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testMethod1WhenMethod2ThrowsException() throws Exception {
thrown.expect(Exception.class);
thrown.expectMessage("expected exception message");
myServive.method1();
}

Junit test: Test multiple Exception

For my application I want to check a function which throws two Exceptions. I want to check these Exceptions by JUnit.
Here an example:
class MyFoo {
public void doSomeStuff(ArrayList<Object> objectList) {
if (objectList.size() >= 2) {
throw new IllegalArgumentException("");
}
if (objectList.size() == 0) {
throw new IllegalArgumentException("");
} else {
//do further Stuff
}
}
}
So now i want to check this function. I know how to test a single exception, but is there a way to check both exception at once? Or is it better to check every exception in a own test?
Here the test for one exception:
public class MyFooTest {
#Rule
public ExpectedException thrown= ExpectedException.none();
#Test
public void testDoSomeStuff() {
thrown.expect(IllegalArgumentException.class);
List<Object> objectList=new ArrayList<>();
objectList.add(new Object());
objectList.add(new Object());
objectList.add(new Object());
doSomeStuff(objectList);
}
}
May be I am totally wrong to check both exception at once. So introduce me.
I would assert that the correct exception is thrown in two different test cases.
#Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionWhenListIsEmpty() {
doSomeStuff(Collections.emptyList());
}
#Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionWhenListIsBiggerThanTwo() {
doSomeStuff(Arrays.asList(new Object(), new Object(), new Object()));
}
If one constraint change, you only change one test. The other one remains unchanged.
I would highly recommend single-path scenarios per method for sanity purposes (if you have 17 exceptions in a single test and that test fails, you get to check all 17 of those possibilities) but you also asked if it was possible. Sure it is, you can use assert.fail with try/catches if you want to stuff everything together, where an expected exception skips over the Fail statement.
#Test
public void testDoSomeStuff() {
List<Object> objectList=new ArrayList<>();
try {
doSomeStuff(objectList);
Assert.fail("Should throw IllegalArgumentException!"):
}
catch(IllegalArgumentException e) {
logger.info("Threw IllegalArgumentException as expected.");
}
objectList.add(new Object());
objectList.add(new Object());
objectList.add(new Object());
try {
doSomeStuff(objectList);
Assert.fail("Should throw IllegalArgumentException!"):
}
catch(IllegalArgumentException e) {
logger.info("Threw IllegalArgumentException as expected.");
}
}
You should create two tests for specific situations. In this case one for each exception will keep the unit tests clean and clear.
You can have two test methods and have the expectation for each type of exception on them. In your case, I think your logic needs only one exception because you can collapse your conditions: if (objectList.isEmpty() || (objectList.size() >= 2))...then check for IllegalArgumentException with different samples.
On the other hand, if you really want to have that separated, have two methods with two expectations: #Test(expected = IllegalArgumentException.class).
#Test(expected = IllegalArgumentException.class)
public void doSomeStuff1() {
doSomeStuff(Collections.emptyList());
}
#Test(expected = IllegalArgumentException.class)
public void doSomeStuff2() {
List<Object> sample = new ArrayList<Object>();
for (int i = 0; i < 5; i++) { // Change `5` for something else if you want
sample.add(new Object());
}
doSomeStuff(sample);
}

Re-run failed test using Junit

I'm trying to improve an existing system of automated Selenium test.
My goal is to repeat the tests that fails because of connections problem.
I've found and tried to follow this thread How to Re-run failed JUnit tests immediately? that revealed itself quite useful.
In my case the suite is composed by classes, so I've tried to substitute #Rule with #ClassRule, in order to repeat for each try also the #Before and #After parts.
I'm sorry for my ignorance, but where am I supposed to place this rule? In my Suite class? Or in the Classes representing the test?
I am the original answerer of How to Re-run failed JUnit tests immediately?
If I understand correctly, the problem that you are having is due to the #Before being executed before the code in the RetryRule, and the #After being executed afterwards.
So your current behaviour is something like:
#Before
#Retry
test code
#Retry
#After
But you can implement your #Before and #After as a rule - there is a rule ExternalResource which does exactly that. You would implement #Before and #After as a rule:
#Rule public ExternalResource beforeAfter = new ExternalResource() {
public void before() {
// code that was in #Before
}
public void after() {
// code that was in #After
}
}
Then you don't need the #Before and #After. You can then chain these rules using RuleChain. This forces an order of execution to your rules:
#Rule public RuleChain chain= RuleChain
.outerRule(new LoggingRule("outer rule")
.around(new LoggingRule("middle rule")
.around(new LoggingRule("inner rule");
so your final solution would be something like:
private ExternalResource beforeAfter = ...
private RetryRule retry = ...
#Rule public RuleChain chain = RuleChain
.outerRule(retry)
.around(beforeAfter);
Note that if you are using RuleChain, you no longer need the #Rule annotation on the ExternalResource and RetryRule, but you do on the RuleChain.
Here is my solution based on the one mentionned in the question.
It's a combinaison of a #Rule, FailedRule and a #ClassRule, RetryRule
public class RetryTest
{
public static class FailedRule implements TestRule
{
#Override
public Statement apply(final Statement base, final Description description)
{
return new Statement()
{
#Override
public void evaluate() throws Throwable
{
try
{
base.evaluate();
}
catch (Throwable t)
{
System.out.println(description.getDisplayName() + " failed");
retry.setNotGood();
if (retry.isLastTry())
{
System.out.println("No more retry !");
throw t;
}
else
{
System.out.println("Retrying.");
}
}
}
};
}
}
public static class RetryRule implements TestRule
{
private int retryCount, currentTry;
private boolean allGood = false;
public RetryRule(int retryCount)
{
this.retryCount = retryCount;
this.currentTry = 1;
}
public boolean isLastTry()
{
return currentTry == retryCount;
}
public void setNotGood()
{
allGood = false;
}
public Statement apply(final Statement base, final Description description)
{
return new Statement()
{
#Override
public void evaluate() throws Throwable
{
// implement retry logic here
for (; currentTry <= retryCount && !allGood; currentTry++)
{
allGood = true;
System.out.println("Try #" + currentTry);
base.evaluate();
}
}
};
}
}
#ClassRule
public static RetryRule retry = new RetryRule(3);
#Rule
public FailedRule onFailed = new FailedRule();
#BeforeClass
public static void before()
{
System.out.println("Before...");
}
#AfterClass
public static void after()
{
System.out.println("...After\n");
}
#Test
public void test1()
{
System.out.println("> test1 running");
}
#Test
public void test2()
{
System.out.println("> test2 running");
Object o = null;
o.equals("foo");
}
}
It gives :
Try #1
Before...
> test1 running
> test2 running
test2(RetryTest) failed
Retrying.
...After
Try #2
Before...
> test1 running
> test2 running
test2(RetryTest) failed
Retrying.
...After
Try #3
Before...
> test1 running
> test2 running
test2(RetryTest) failed
No more retry !
...After
If I am commenting the o.equals("foo"); in test2, everything runs fine in the firt try :
Try #1
Before...
> test1 running
> test2 running
...After
You decorate the test name itself with the #After or #Afterclass attributes:
#After
#Test
#Category(SmokeTests.class)
public void testProductPageOnly() throws TimeoutException {
//Some tests here.
}
#Afterclass
public static void SomeTest {
//Some test here.
}
Something to note, #Afterclass will always run; even if you are using a #Beforeclass that throws an exception.
May this can solve problem:
1) Test class should be inherited from junit.framework.TestCase
2) Run your tests with something like this
YourTestClass testClass = new YourTestClass();
TestResult result = testClass.run();
Enumeration<TestFailure> failures = result.failures();
if (result.failureCount() != 0)
{
TestFailure fail = failes.nextElement();
junit.framework.Test test = fail.failedTest();
test.run( result );
}
At the end result will contains last results of test running, so after analyzing what test was failed you can run it again.

Expect an exception or one of its subclasses in Junit Test using #Test annotation

I have a test that expects a particular exception, for example:
#Test(expected=MyException.class)
public void testMyMethod(){
myMethod();
}
The myMethod() method actually throws a subclass of MyException, lets call it MySubclassException.
Is there anyway to define my test using the #Test annotation to accept subclasses of MyException as well as the class itself?
I know that I could simply write the test checking logic myself without using expected by catching the exception and setting a flag, but I was wondering whether or not JUnit already supported matching exception subclasses.
This is already handled for you by the framework
Let's take a small example (very bad code):
import static org.junit.Assert.*;
import org.junit.Test;
public class TestExpect {
#Test(expected=MyException.class)
public void test() throws MyException {
new Foo().foo();
}
}
With 2 exception classes MyException and MyExtendedException inheriting from the previous one and a simple Foo class like this one:
public class Foo {
public void foo() throws MyException{
throw new MyExtendedException();
}
}
Launching the test using the Eclipse runner prints a green bar because the test raises one instance of Myexception (is a relationship in POO)
If you prefer to read source code this is an exxcerpt from the Junit source code (ExpectException.java):
#Override
public void evaluate() throws Exception {
boolean complete = false;
try {
fNext.evaluate();
complete = true;
} catch (AssumptionViolatedException e) {
throw e;
} catch (Throwable e) {
if (!fExpected.isAssignableFrom(e.getClass())) {
String message= "Unexpected exception, expected<"
+ fExpected.getName() + "> but was<"
+ e.getClass().getName() + ">";
throw new Exception(message, e);
}
}
if (complete)
throw new AssertionError("Expected exception: "
+ fExpected.getName());
}
The test will pass if MyException or MySubclassException is thrown by myMethod(). I tested the concept with this code:
public class ExceptionTest {
private static class ExceptionA extends Exception {
}
private static class ExceptionB extends ExceptionA {
}
#Test(expected=ExceptionA.class)
public void test() throws Exception {
throw new ExceptionB();
}
}
BDD Style Solution with Catch Exception
#Test
public void testMyMethod() {
when(foo).myMethod();
then(caughtException()).isInstanceOf(MyException.class);
}
Dependencies
com.googlecode.catch-exception:catch-exception:1.2.0

Categories