I've found the proper use (or at least the documentation) of JUnit very confusing. This question serves both as a future reference and as a real question.
If I've understood correctly, there are two main approaches to create and run a JUnit test:
Approach A (JUnit 3-style): create a class that extends TestCase, and start test methods with the word test
. When running the class as a JUnit Test (in Eclipse), all methods starting with the word test
are automatically run.
import junit.framework.TestCase;
public class DummyTestA extends TestCase {
public void testSum() {
int a = 5;
int b = 10;
int result = a + b;
assertEquals(15, result);
}
}
Approach B (JUnit 4-style): create a 'normal' class and prepend a @Test
annotation to the method. Note that you do NOT have to start the method with the word test
.
import org.junit.*;
import static org.junit.Assert.*;
public class DummyTestB {
@Test
public void Sum() {
int a = 5;
int b = 10;
int result = a + b;
assertEquals(15, result);
}
}
Mixing the two seems not to be a good idea, see e.g. this stackoverflow question:
Now, my questions(s):
@Test(expected = ArithmeticException.class)
. But how do you test for exceptions when using approach A?When using approach A, you can group a number of test classes in a test suite like this:
TestSuite suite = new TestSuite("All tests");
suite.addTestSuite(DummyTestA.class);
suite.addTestSuite(DummyTestAbis.class);
But this can't be used with approach B (since each testclass should subclass TestCase). What is the proper way to group tests for approach B?
Edit: I've added the JUnit versions to both approaches
The distinction is rather easy:
TestCase
is the way unit tests were written in JUnit 3 (of course it's still supported in JUnit 4)@Test
annotation is the way introduced by JUnit 4Generally you should choose the annotation path, unless compatibility with JUnit 3 (and/or a Java version earlier than Java 5) is needed. The new way has several advantages:
@Test
annotaton is more explicit and is easier to support in tools (for example it's easy to search for all tests this way)@Before
/@BeforeClass
and @After
/@AfterClass
providing more flexibility@Rule
annotations on things like ExpectedException
@Ignored
annotation@RunWith
To test for expected exceptions in a JUnit 3 TestCase
you'd have to make the text explicit.
public void testMyException() {
try {
objectUnderTest.myMethod(EVIL_ARGUMENT);
fail("myMethod did not throw an Exception!");
} catch (MyException e) {
// ok!
// check for properties of exception here, if desired
}
}
JUnit 5 introduced yet another API change, but still uses annotations. The new @Test
annotation is org.junit.jupiter.api.Test
(the "old" JUnit 4 one was org.junit.Test
), but it works pretty much the same as the JUnit 4 one.