As you may be aware, couple of the touted "benefits" of JUnit 4 are the obviation of extending the
TestCase
class and the identification of test and lifecycle methods (setUp
and tearDown
) using Java 5 annotations. For example, the following is a valid JUnit 4-style test case (minus the necessary imports):public class BusinessLogicTests {
@Before
public void do_this_before_every_test() {
// set up logic goes here
}
@After
public void clean_up_after_a_test() {
// teardown logic goes here
}
@Test
public void addition() {
assertEquals("Invalid addition", 2, 1+1);
}
}
Observe how
- The class does not extend
TestCase
- The "setup" and "tearDown" methods are identified by annotations
- The test method does not require a "test" prefix and is also annotated
I'll let you be the judge of whether this is an improvement on JUnit 3. What I want to alert you to are the perils of subconciously mixing JUnit-3 and JUnit-4 style programming. Consider the following test case:
public class BusinessLogicTests extends TestCase {
@Before
public void do_this_before_every_test() {
// set up logic goes here
}
@After
public void clean_up_after_a_test() {
// teardown logic goes here
}
@Test
public void testAddition() {
assertEquals("Invalid addition", 2, 1+1);
}
@Test
public void subtraction() {
assertEquals("Invalid subtraction", 1, 1-1);
}
}
This will result in a green-bar even though there is an error in the test of subtraction. Can you guess why?
It was that pesky little
extends TestCase
that I added from force of habit. The flips the switch to JUnit-3, which knows nothing about annotations, ignores my setup and teardown methods and looks for methods prefixed by test
. It completely ignores the method named subtraction!And of course, conversely, the following is just a plain old Java class that won't be acknowledged by either JUnit-3 or JUnit-4.
public class BusinessLogicTests {
public void testAddition() {
assertEquals("Invalid addition", 2, 1+1);
}
}
Final word of advice, if you are using Struts Test Case, you have no choice but to write JUnit-3 style tests since the parent class of the framework (MockStrutsTestCase) extends Junit-3's TestCase.
Good finding! but misleading in many ways.
ReplyDeleteAs the issue (of not running another test case), would be found in many ways.
Compile Time:
- extends 'TestCase' not needed any more. the very first sentence that catches your eye when you read any v.4 documentation.
- assertEquals() & similar others, are imported as static, v.4 & JDK5
Runtime:
- When you run the eg. code for v.3, say in eclipse, you'd see only one test run.
By the way, what are the underscores in the name of the methods,
clean_up_after_a_test?!
Excellent example. This is exactly the problem I am running into now. I am moving to junit4, but would like to keep the old junit3 code. I would like to add new tests using junit4 annotation and still allow both versions of tests to be executed.
ReplyDeleteWere you able to get both tests to execute in your example? If so, how was it done?
@cwwojcik
ReplyDeleteYou *can* run JUnit3 & JUnit4-style unit tests in the same project -- just not in the same class.
For JUnit3-style you must extend JUnit's TestCase class. On the other hand for JUnit4 you simply use the annotations. You can run them both as part of the same build.
same problem, I want to keep extending junit 3 base classes but still be able to write JUnit 4 style test methods and setup and teardowns...
ReplyDeleteI found that sometimes it works overriding setup and teardown (if there is a base class with fixture fuctionality) and annotating the overrided methods with @Before and @After... but not pretty sure if it would work always...
Thanks for the post! I wish I found this before I started converting to JUnit4. I linked to this post from my blog, Hacker's Valhalla, as I wrote a related post about unit testing. Thank you again.
ReplyDelete