JUnit4 Annotations are a single big change from JUnit 3 to JUnit 4 which is introduced in Java 5. With annotations creating and running a JUnit test becomes easier and more readable, but you can only take full advantage of JUnit4 if you know the correct meaning of annotations used on this version and how to use them while writing tests. In this
Junit tutorial we will not only understand the meaning of those annotations but also we will see examples of JUnit4 annotations. By the way, this is my first post in unit testing but if you are new here than you may like post 10 tips to write better code comments and 10 Object-oriented design principles for Programmer as well.
JUnit 4 Annotations: Overview
Following is a list of frequently used Annotations, which is available when you include junit4.jar in your Classpath:
@Before
@BeforeClass
@After
@AfterClass
@Test
@Ignore
@Test(timeout=500)
@Test(expected=IllegalArgumentException.class)
@BeforeClass
@After
@AfterClass
@Test
@Ignore
@Test(timeout=500)
@Test(expected=IllegalArgumentException.class)
And, if you are new to unit testing and just looking for good online training courses to learn unit testing in Java then I highly recommend you check out these JUnit and Mockito courses for Java programmers. It's a good resource to learn JUnit 5 in easy-to-follow steps.
@Before and @After
In Junit4 there is no setup() or tearDown() method and instead of that we have @Before and @After annotations.
By using @Before you can make any method as setup() and by using @After you can make any method as teardown(). What is the most important point to remember is @Before and @After annotated method will be invoked before and after each test case.
So in case, you have five test cases in your JUnit test file then just like setup() and tearDown() method annotated with @Before and @After will be called five times. Here is an example of using @Before and @After Annotation :
So in case, you have five test cases in your JUnit test file then just like setup() and tearDown() method annotated with @Before and @After will be called five times. Here is an example of using @Before and @After Annotation :
@Before
public void setUp() {
System.out.println("@Before method will execute before every JUnit4 test");
}
@After
public void tearDown() {
System.out.println("@After method will execute after every JUnit4 test");
}
public void setUp() {
System.out.println("@Before method will execute before every JUnit4 test");
}
@After
public void tearDown() {
System.out.println("@After method will execute after every JUnit4 test");
}
@BeforeClass and @AfterClass
@BeforeClass and @AfterClass JUnit4 Annotations are similar to @After and @Before with the only exception that they are called on per TestClass basis and not on a per-test basis. They can be used for a one-time setup and tearDown method and can be used to initialize class level resources.
Here is an example of using @BeforeClass and @AfterClass Annotations in JUnit4, here is an example of @BeforeClass and @AfterClass Junit 4 annotation
Here is an example of using @BeforeClass and @AfterClass Annotations in JUnit4, here is an example of @BeforeClass and @AfterClass Junit 4 annotation
@BeforeClass
public static void setUpClass() throws Exception {
System.out.println("@BeforeClass method will be executed before the JUnit test for"
+ "a Class starts");
}
@AfterClass
public static void tearDownClass() throws Exception {
System.out.println("@AfterClass method will be executed after JUnit test for"
+ "a Class Completed");
}
public static void setUpClass() throws Exception {
System.out.println("@BeforeClass method will be executed before the JUnit test for"
+ "a Class starts");
}
@AfterClass
public static void tearDownClass() throws Exception {
System.out.println("@AfterClass method will be executed after JUnit test for"
+ "a Class Completed");
}
@Test
@Test is a replacement of both TestCase class and convention "test" which we prefix to every test method. for example, to test a method called calculateInterest() we used to create method testCalcuatedInterest() and our class needs to be extended from org.junit.TestCase class. Now with @Test annotation that is not required anymore. You just need to annotate your test method with @Test Junit4 annotation and done. no need to extend from TestCase class and no need to prefix "test" to your method, here is an example of JUnit 4 @Test annotation
@Test
public void testCalculateInterest() {
System.out.println("calculateInterest");
fail("An Example of @Test JUnit4 annotation");
}
public void testCalculateInterest() {
System.out.println("calculateInterest");
fail("An Example of @Test JUnit4 annotation");
}
@Ignore
Some time we add test method in JUnit test class but hasn't implemented that is causing your build to fail if JUnit testcase are integrated or embedded into build process. you can avoid that problem by marking your test method as @Ignore in Junit4. JUnit4 ignores method annotated with @Ignore and doesn't run during test. Here is an example of using @Ignore annotation in JUnit4 to exclude a particular Test from running:
@Ignore("Not yet implemented")
@Test
public void testGetAmount() {
System.out.println("getAmount");
fail("@Ignore method will not run by JUnit4");
}
@Test
public void testGetAmount() {
System.out.println("getAmount");
fail("@Ignore method will not run by JUnit4");
}
@Test(timeout=500)
Now with JUnit4 writing testcases based on timeout is extremely easy. You just need to pass a parameter timeout with value in millisecond to @Test annotation. remember timeout values are specified in millisecond and your JUnit4 timeout test case will help if it doesn't complete before timeout period. This works great if you have SLA(Service Level Agreement) and an operation need to complete before predefined timeout.
@Test(timeout = 500)
public void testTimeout() {
System.out.println("@Test(timeout) can be used to enforce timeout in JUnit4 test case");
while (1 == 1) {
}
}
public void testTimeout() {
System.out.println("@Test(timeout) can be used to enforce timeout in JUnit4 test case");
while (1 == 1) {
}
}
This JUnit4 test will fail after 500 millisecond.
@Test(expected=IllegalArgumentException.class)
Another useful enhancement is Exception handling testcases of JUnit4. Now to test Exception is become very easy and you just need to specify Exception class inside @Test annotation to check whether a method throws a particular exception or not. here is an example which test behaviour of a method to verify whether it throws Exception or not, when run with invalid input:
@Test(expected=IllegalArgumentException.class)
public void testException(int input) {
System.out.println("@Test(expected) will check for specified exception during its run");
}
public void testException(int input) {
System.out.println("@Test(expected) will check for specified exception during its run");
}
These were a list of frequently used JUnit 4 annotations and their meanings. In the course we have also learned how to use @Before, @After in place of setup() and teardown(). Code review and Unit testing is one of the best development practices to follow and we must try our best to incorporate that in our daily coding and development cycle.
Thank you, I hope you will continue about JUnit, because it is essential framework for modern programming.
ReplyDelete@Jirka Pinkas, Thanks mate.I agree JUnit is essential testing framework and must sit well on top on developer's TODO list. I will definitely try to bring more JUnit tutorials and practical examples of how to test certain features in Java.
ReplyDeleteJavin
The last code snippet is an invalid JUnit test as a test method must not have any parameters.
ReplyDeleteThanks @Simon Harrer, that's mistake. JUnit test method should not have any parameter, thanks for pointing that.
ReplyDelete@JohnMunsch, Thank, you added which is most common practice after @Test introduction,still some people follow test naming convention , but I like short names of method just like you. Thanks for highlighting that.
ReplyDeleteHi, I am new to all of this and trying to learn. The second code snippet I find a little confusing "@After method will execute before every JUnit4 test". Shoulld this state it runs AFTER every test JUnit test? and not BEFORE?
ReplyDeleteThank you
Jamie
@Jamie, A classical copy paste mistake. Thanks for pointing that out. You are correct method annotated with @After runs AFTER every JUnit test. Apologies for confusion, corrected now.
ReplyDeleteTo better highlight with your example that tests no longer have to follow a naming convention, I would have named the function differently. For example,
ReplyDelete@Test
public void calcInterest() {
System.out.println("calcInterest");
fail("An Example of @Test JUnit4 annotation");
}
Now the example reinforces what the explanatory text says.