Reputation: 373
I've learnt how to catch an exception in Junit testing. but now I want to loop through arguments which can cause the exception {null, Object.class}
currently the test runs for the first loop then exists with a pass and does not check the next loop argument.
@Rule
public ExpectedException ee;
public ClassTest() {
this.ee = ExpectedException.none();
}
/**
* Test of isCompramised method.
*/
@Test
public void testIsCompramised2() {
System.out.println("isCompramised Exception");
Class<?>[] c = {null, Object.class};
for (Class<?> class1 : c) {
MyClass instance = new MyClass();
ee.expect(IllegalArgumentException.class);
boolean result = instance.isCompramised(class1);
fail("Exception should have been thrown");
}
}
So I tried this, it completes the for loop but all the expected exceptions fail as i think Try Catch now steals the exception.
/**
* Test of isCompramised method, of class MyClass.
*/
@Test
public void testIsCompramised2() {
System.out.println("isCompramised Exception");
Class<?>[] c = {null, Object.class};
for (Class<?> class1 : c) {
MyClass instance = new MyClass();
try{
ee.expect(IllegalArgumentException.class);
boolean result = instance.isCompramised(class1);
fail("Exception should have been thrown");
} catch (Exception e){
continue;
}
}
}
Suggestions please?
Is this correct?
try{
boolean result = instance.isCompramised(class1);
fail("Exception should have been thrown");
} catch (Exception e){
AssertTrue(e instanceOf IllegalArgumentException);
continue;
}
Upvotes: 2
Views: 3157
Reputation:
As this is the first google result when searching I want to add my solution.
In my example Datum throws an exception if the date gets invalid arguments in the constructor.
To test this I wanted to test that the constructor will not accept invalid input and throw an exception.
I test a range of example-cases that should be rejected with a for loop.
To test that the loop threw an exception in every iteration I simply added a boolean variable that was set true in a catch for this exact exception on every iteration, if the variable was false at the end of the iteration then a runtime exception would be thrown that will let the test fail.
I think this is far easier to read for teammembers afterwards without any extravagant knowledge for junit tests. It is much easier to use for beginners as well.
package übungen.blatt_01;
import org.junit.Test;
public class DatumTest {
@Test
public void testConstructor() throws Exception {
for(int jahr = 1801; jahr <2010; jahr++) {
for(int monat = 1; monat <= 12; monat++) {
for(int tag = 1; tag <= Datum.getMonatslänge(monat, jahr); tag++) {
try{
new Datum(tag,monat,jahr);
}
catch(Exception e){System.out.println(tag+","+monat+","+jahr); e.printStackTrace(); return;}
}
}
}
}
@Test
public void testAllExclusive() {
boolean failAsExpected = false;
for(int jahr = 1801; jahr <2010; jahr++) {
for(int monat = 12+1; monat <= 24; monat++) {
for(int tag = 32; tag <= 60; tag++) {
failAsExpected=false;
try {
testConstructorErrors(tag,monat,jahr);
}catch(DateOutOfRangeException e){
failAsExpected=true;
}
if(!failAsExpected)
throw new RuntimeException("test failed");
}
}
for(int monat = -1; monat >= -24; monat--) {
for(int tag = -1; tag >= -60; tag--) {
try {
testConstructorErrors(tag,monat,jahr);
}catch(DateOutOfRangeException e){
failAsExpected=true;
}
if(!failAsExpected)
throw new RuntimeException("test failed");
}
}
}
}
public void testConstructorErrors(int tag, int monat, int jahr) {
//put additional code here to increase readability of the test loop
new Datum(tag,monat,jahr);
}
}
Upvotes: 0
Reputation:
I would go with something like that:
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import java.util.Arrays;
@RunWith(Parameterized.class)
public class Foo {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Parameter
public Class<?> input;
/**
* Test of isCompramised method, of class MyClass.
*/
@Test
public void testIsCompramised() {
this.expectedException.expect(IllegalArgumentException.class);
final MyClass instance = new MyClass();
instance.isCompramised(input);
}
@Parameters(name = "test for {0}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] { {null}, {Object.class} });
}
}
(or two test methods, one for null
and one for Object
)
EDIT: some complements (see comments)
The methods annotated with @Parameters
returns an Iterable
containing Object[]
. Each of those Object[]
is bound to a @Parameter
annotated field (using the value of @Parameter
as index [default: 0]).
JUnit Parameterized
runner will iterate over the @Parameters
data and for each array, set fields values and then run every tests in the class.
See also: Parameterized
javadoc
Upvotes: 3
Reputation: 8938
Catching and checking the exception manually within the loop, instead of using expect
, may be the way to go there. Your "is this correct" code block should work if placed within the loop.
Upvotes: 0