Unit Testing Using Junit+Annotation

Junit + Annotation = Powerful Way of Unit Testing


02 Aug 2016 View Comments
#unit #testing #computer #java

Here are some annotation and their usages that I have come across when I am testing using JUnit

  • @BeforeClass – Run once before any of the test methods in the class, public static void
  • @AfterClass – Run once after all the tests in the class have been run, public static void
  • @Before – Run before @Test, public void
  • @After – Run after @Test, public void
  • @Test – This is the test method to run, public void
package test.testCase;

import org.junit.*;

public class BasicAnnotationTest {

    // Run once, e.g. Database connection, connection pool
    @BeforeClass
    public static void runOnceBeforeClass() {
        System.out.println("@BeforeClass - runOnceBeforeClass");
    }

    // Run once, e.g close connection, cleanup
    @AfterClass
    public static void runOnceAfterClass() {
        System.out.println("@AfterClass - runOnceAfterClass");
    }

    // Should rename to @BeforeTestMethod
    // e.g. Creating an similar object and share for all @Test
    @Before
    public void runBeforeTestMethod() {
        System.out.println("@Before - runBeforeTestMethod");
    }

    // Should rename to @AfterTestMethod
    @After
    public void runAfterTestMethod() {
        System.out.println("@After - runAfterTestMethod");
    }

    @Test
    public void test_method_1() {
        System.out.println("@Test - test_method_1");
    }

    @Test
    public void test_method_2() {
        System.out.println("@Test - test_method_2");
    }

}
  • @RunWith – You can also assign a @RunWith annotation to indicate what class JUnit to be handled with. Below is example usage of Parameterized.class.
package test.testCase;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.Arrays;
import java.util.Collection;

import static org.junit.Assert.assertEquals;

/**
 * Created by calvin.lee on 2016-08-15.
 */
@RunWith(Parameterized.class)
public class ParameterizedTest {
    private int expected;
    private int valueOne;
    private int valueTwo;

    @Parameterized.Parameters
    public static Collection getTestParameters() {
        return Arrays.asList(new Integer[][] {
                { 2, 1, 1 },
                { 3, 2, 1 },
                { 4, 3, 1 }
        });
    }

    public ParameterizedTest(int expected, int valueOne, int valueTwo) {
        this.expected = expected;
        this.valueOne = valueOne;
        this.valueTwo = valueTwo;
    }

    @Test
    public void testAdd() {
        assertEquals(expected, add(valueOne, valueTwo));
    }

    private int add (int a, int b) {
        if (a == 0) return b;
        while (b != 0) {
            int carry = a & b;
            a = a ^ b;
            b = carry << 1;
        }
        return a;
    }
}
  • @Suite – This annotation is used to bundle test cases and run them together. You would use both @RunWith and @Suite annotations. Let’s say you already have TestSomething1 & TestSomething2 that runs the tests fine. Now in order to run them together, you can create a class called something like TestSuite and put them all in there like example below.
package test.testCase;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)

@Suite.SuiteClasses({
   TestSomething1.class,
   TestSomething2.class
})

public class TestSuite {   
}  
  • @Ignore – mainly used for temporarily disabling a test or a group of tests. Simply adding this above a function will ignore this unit test to be included:
...
    @Ignore
    @Test
    public void something() { ...
...

If you require to ignore the entire class, you can

...
    @Ignore
    public class IgnoreMe {
        @Test public void test1() { ... }
        @Test public void test2() { ... }
    }
...
  • Mockito - You will require to include dependancy library and add into your classpath called mokito-all. The test do not necessarily require any special annotation but I thought it worthwhile to mention here. Basic idea of Mocking an object is to create an accessible object for unit test to work. For more information: [Mockito](https://www.tutorialspoint.com/mockito/)
  • @RuleRules allow very flexible addition or redefinition of the behavior of each test method.

NOTE: I have never used below annotations in the practice, however, they seem interesting after reading about them.

  • @Category, @IncludeCategory, @ExcludeCategory: You can group tests into Categories.
  • @DataPoint, @DataPoints, @FromDataPoints, @ParametersSuppliedBy: Annotating an field or method with @DataPoint will cause the field value or the value returned by the method to be used as a potential parameter for theories in that class. Annotating a parameter of a @Theory method with @FromDataPoints will limit the datapoints considered as potential values for that parameter to just the @DataPoints with the given name. Annotating a @Theory method parameter with @ParametersSuppliedBy causes it to be supplied with values from the named ParameterSupplier when run as a theory.
  • @TestedOn: The @TestedOn annotation takes an array of values to be used as data points for the annotated parameter.
    @Theory
    ...
       public void multiplyIsInverseOfDivideWithInlineDataPoints(
            @TestedOn(ints = {0, 5, 10}) int amount,
            @TestedOn(ints = {0, 1, 2}) int m
       ) {
           assumeThat(m, not(0));
           assertThat(new Dollar(amount).times(m).divideBy(m).getAmount(), is(amount));
       }
    ...
Share this post

Me

I am a passionate programmer working in Vancouver. I strongly believe in art of algorithms and together with it to write clean and efficient software to build awesome products. If you would like to connect with me, choose one from below options :) You can also send me an email at