Recently I looked through some JUnit 3.8 - JUnit 4 stuffs. Here are two useful readings in the subject: First is at IBM, other is on DevX. JUnit 4.X is basically direct improvement of JUnit 3.X with exploiting new features of JDK5. Current version is 4.4 and it can be downloaded from www.junit.org. What have been changed?
If you need this in Hungarian, click here.
- It needs (surprisingly) at least Java 5.
- Package has been changed from
junit.framework
toorg.junit
. - Using
@Test
annotations instead of naming conventions. Methods must be public withvoid
return type and they shouldn't have parameters. If we don't comply with these we would expect the following runtime exceptions:java.lang.Exception: Method xxx should have no parameters
java.lang.Exception: Method xxx should be void - Using static import:
import static org.junit.Assert.assertEquals;
We can write instead ofAssert.assertEquals(...);
a sorterassertEquals(...);
. (Of course we can use static import with JUnit 3.8 if we have Java 5.) - Extending
TestCase
isn't necessary anymore, so it becames possible to test protected methods by extending the subject class with the class which has the tests. - Instead of method
setUp()
we use@Before
annotation, even more than one. Order of executing these methods is theoretically random. tearDown()
's annotation pair is@After
, which we can have also more than one.- In super classes we haven't have to invoke explicite
setUp()==@Before
andtearDown()==@After
methods because their invocation is automatic: First@Before
-s of the super class are invoked, then ones in descendant classes. Order of invoking@After
is reversed. First the descendant classes, then super classes. - A
@Before
and@After
is invoked before and after every test method assetUp()
andtearDown()
does. We have the possibility to concede@BeforeClass
and@AfterClass
which will be invoked before and after all test methods in the given class. There is no such feature in JUnit 3.X. (It hasTestSuite
class which ensures similar functionality.) - If a class doesn't have any
@Test
annotation, we will get an error. - In JUnit 3.X we could check exceptions by writing an
assert
into thecatch
block. In JUnit 4 we can define expected exceptions in annotation:@Test(expected=ArithmeticException.class)
. If exception isn't thrown or different exception has been thrown the test will fail. If more checks needed about parameters and message of the thrown exceptions we must follow the well-knowntry-catch
practice. - If we don't want to run some test methods for some reason it's possible to ignore it by using
@Ignore
. (@Test
needn't have to be removed.@Ignore
can follow or precede it.) It can have a String-type parameter with the reason why is the test ignored. Test won't run and the runner will sign the fact that it was ignored. We can say@Ignore
for the whole class but it's slightly differs from ignoring each test methods one by one, because@AfterClass
and@BeforeClass
will run in the latter case. - Highly appreciated feature to be able to give timeout for the test cases:
@Test(timeout=500)
Millisec. - There is a new assert which compares object arrays, however many (12) assert method removed because of the autoboxing feature.
assertXXX(Object, Object)
is used instead of them. More precisely DevX writes this happened but oddly I can use these old asserts in theTestCase
class. assert
keyword of Java1.4 can also be used, however-ea
JVM switch must be given at running the tests, otherwiseassert
s won't be evaluated. When using native asserts, instead of the JUnit'sassertException
, the generaljava.lang.AssertionError
will raise in certain cases.- In JUnit4 there is no
suite()
method. We can create an empty class which has the runnable classes in annotation:@RunWith(Suite.class)
@Suite.SuiteClasses({My1Test.class, My2Test.class, My2Test.class})public class AllTests {
} - By using
@RunWith
class annotation we can define own runner for the test cases. For an example, theorg.junit.runners.Parameterized
, which drives the test by a set of parameters we defined previously. A public static method with@Parameters
annotation is needed which returns aCollection
and a public constructor is needed which can accept elements of the previous Collection. If the Collection contains integer pairs, constructor must have two integer parameters. The runner walks through on the Collection, calls the constructor and the test methods for every element of the Collection. DevX article has a good example about this on the third page. (Listing 2.) - Giving
@RunWith(TestClassRunner.class)
doesn't make any difference than giving anything because theTestClassRunner
is the default runner. - JUnit4 doesn't make difference between expected failures and wrongly written test cases. This is a stepback. One testcase can have (passed/error/failure) in JUnit 3.8. In JUnit 4 it can have (passed/failure/(ignored)) only.
- Test can be runned by
java –ea org.junit.runner.JUnitCore
. It can run 3.8 tests according to the DevX article. Practically 3.8 must have a small modification:public static junit.framework.Test suite() {
return new JUnit4TestAdapter(MyTestClass.class);
4.0 tests certainly won't run on 3.8. When having both old and new JUnit on the classpath they may impact. It least I had securityException. - I've heard about a so called
assertThat
method. Theoretically 4.4 have this but I didn't see it in the current javadoc on junit.org. - Eclipse 3.3 has JUnit4.4 and JUnit3.8 support.
If you need this in Hungarian, click here.
Comments