Thursday, October 2, 2014

JUnit

Important APIs of JUnit:

Some of the important classes are:
- Assert: set of assert methods.
- TestCase: defines fixture to run multiple tests.
- TestResult: collects results of executing a testcase.
- TestSuite: composite of tests.

Assert class:

- public class Assert extends java.lang.Object.

Methods:

1void assertEquals(boolean expected, boolean actual)
Check that two primitives/Objects are equal
2void assertFalse(boolean condition)
Check that a condition is false
3void assertNotNull(Object object)
Check that an object isn't null.
4void assertNull(Object object)
Check that an object is null
5void assertTrue(boolean condition)
Check that a condition is true.
6void fail()
Fails a test with no message.

Create a java class file name TestJunit1.java in C:\ > JUNIT_WORKSPACE

import org.junit.Test;
import static org.junit.Assert.*;
public class TestJunit1 {
   @Test
   public void testAdd() {
      //test data
      int num= 5;
      String temp= null;
      String str= "Junit is working fine";

      //check for equality
      assertEquals("Junit is working fine", str);
      
      //check for false condition
      assertFalse(num > 6);

      //check for not null value
      assertNotNull(str);
   }
}
Next, let's create a java class file name TestRunner1.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner1 {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestJunit1.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}   
Compile the Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac TestJunit1.java TestRunner1.java
Now run the Test Runner which will run test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner1
Verify the output.
true

Test case class.

Following is the declaration for org.junit.TestCaset class:
public abstract class TestCase extends Assert implements Test
A test case defines the fixture to run multiple tests. Some of the important methods of TestCase class are
S.N.Methods & Description
1int countTestCases()
Counts the number of test cases executed by run(TestResult result).
2TestResult createResult()
Creates a default TestResult object.
3String getName()
Gets the name of a TestCase.
4TestResult run()
A convenience method to run this test, collecting the results with a default TestResult object.
5void run(TestResult result)
Runs the test case and collects the results in TestResult.
6void setName(String name)
Sets the name of a TestCase.
7void setUp()
Sets up the fixture, for example, open a network connection.
8void tearDown()
Tears down the fixture, for example, close a network connection.
9String toString()
Returns a string representation of the test case.
Let's try to cover few of the above mentioned methods in an example. Create a java class file name TestJunit2.java in C:\ > JUNIT_WORKSPACE
import junit.framework.TestCase;
import org.junit.Before;
import org.junit.Test;
public class TestJunit2 extends TestCase  {
   protected double fValue1;
   protected double fValue2;
   
   @Before 
   public void setUp() {
      fValue1= 2.0;
      fValue2= 3.0;
   }
 
   @Test
   public void testAdd() {
      //count the number of test cases
      System.out.println("No of Test Case = "+ this.countTestCases());
  
      //test getName 
      String name= this.getName();
      System.out.println("Test Case Name = "+ name);

      //test setName
      this.setName("testNewAdd");
      String newName= this.getName();
      System.out.println("Updated Test Case Name = "+ newName);
   }
   //tearDown used to close the connection or clean up activities
   public void tearDown(  ) {
   }
}
Next, let's create  a java class file name TestRunner2.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner2 {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestJunit2.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
} 
Compile the Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac TestJunit2.java TestRunner2.java
Now run the Test Runner which will run test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner2
Verify the output.
No of Test Case = 1
Test Case Name = testAdd
Updated Test Case Name = testNewAdd
true

TestResult Class

Following is the declaration for org.junit.TestResult class:
public class TestResult extends Object
A TestResult collects the results of executing a test case. It is an instance of the Collecting Parameter pattern. The test framework distinguishes between failures and errors. A failure is anticipated and checked for with assertions. Errors are unanticipated problems like an ArrayIndexOutOfBoundsException. Some of the important methods of TestResult class are
S.N.Methods & Description
1void addError(Test test, Throwable t)
Adds an error to the list of errors.
2void addFailure(Test test, AssertionFailedError t)
Adds a failure to the list of failures.
3void endTest(Test test)
Informs the result that a test was completed.
4int errorCount()
Gets the number of detected errors.
5Enumeration<TestFailure> errors()
Returns an Enumeration for the errors.
6int failureCount()
Gets the number of detected failures.
7void run(TestCase test)
Runs a TestCase.
8int int runCount()
Gets the number of run tests.
9void startTest(Test test)
Informs the result that a test will be started.
10void stop()
Marks that the test run should stop.
Create a java class file name TestJunit3.java in C:\ > JUNIT_WORKSPACE
import org.junit.Test;
import junit.framework.AssertionFailedError;
import junit.framework.TestResult;

public class TestJunit3 extends TestResult {
   // add the error
   public synchronized void addError(Test test, Throwable t) {
      super.addError((junit.framework.Test) test, t);
   }

   // add the failure
   public synchronized void addFailure(Test test, AssertionFailedError t) {
      super.addFailure((junit.framework.Test) test, t);
   }
   @Test
   public void testAdd() {
   // add any test
   }
   
   // Marks that the test run should stop.
   public synchronized void stop() {
   //stop the test here
   }
}
Next, let's create a java class file name TestRunner3.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner3 {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestJunit3.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}   
Compile the Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac TestJunit3.java TestRunner3.java
Now run the Test Runner which will run test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner3
Verify the output.
true

Test Suite class:

Following is the declaration for org.junit.TestSuite class:
public class TestSuite extends Object implements Test
A TestSuite is a Composite of Tests. It runs a collection of test cases. Some of the important methods ofTestSuite class are
S.N.Methods & Description
1void addTest(Test test)
Adds a test to the suite.
2void addTestSuite(Class<? extends TestCase> testClass)
Adds the tests from the given class to the suite.
3int countTestCases()
Counts the number of test cases that will be run by this test.
4String getName()
Returns the name of the suite.
5void run(TestResult result)
Runs the tests and collects their result in a TestResult.
6void setName(String name)
Sets the name of the suite.
7Test testAt(int index)
Returns the test at the given index.
8int testCount()
Returns the number of tests in this suite.
9static Test warning(String message)
Returns a test which will fail and log a warning message.
Create a java class file name JunitTestSuite.java in C:\ > JUNIT_WORKSPACE to create Test suite
import junit.framework.*;
public class JunitTestSuite {
   public static void main(String[] a) {
      // add the test's in the suite
      TestSuite suite = new TestSuite(TestJunit1.class, TestJunit2.class, TestJunit3.class );
      TestResult result = new TestResult();
      suite.run(result);
      System.out.println("Number of test cases = " + result.runCount());
    }
}
Compile the Test suite classes using javac
C:\JUNIT_WORKSPACE>javac JunitTestSuite.java 
Now run the Test Suite.
C:\JUNIT_WORKSPACE>java JunitTestSuite
Verify the output.
No of Test Case = 1
Test Case Name = testAdd
Updated Test Case Name = testNewAdd
Number of test cases = 3

Complete example of JUnit testing using POJO classes.

EmployeeDetails.java

public class EmployeeDetails {

   private String name;
   private double monthlySalary;
   private int age;
   
   /**
   * @return the name
   */
   public String getName() {
      return name;
   }
   /**
   * @param name the name to set
   */
   public void setName(String name) {
      this.name = name;
   }
   /**
   * @return the monthlySalary
   */
   public double getMonthlySalary() {
      return monthlySalary;
   }
   /**
   * @param monthlySalary the monthlySalary to set
   */
   public void setMonthlySalary(double monthlySalary) {
      this.monthlySalary = monthlySalary;
   }
   /**
   * @return the age
   */
   public int getAge() {
      return age;
   }
   /**
   * @param age the age to set
   */
   public void setAge(int age) {
   this.age = age;
   }
}
EmployeeDetails class is used to
  • get/set the value of employee's name.
  • get/set the value of employee's monthly salary.
  • get/set the value of employee's age.
EmpBusinessLogic.java

public class EmpBusinessLogic {
   // Calculate the yearly salary of employee
   public double calculateYearlySalary(EmployeeDetails employeeDetails){
      double yearlySalary=0;
      yearlySalary = employeeDetails.getMonthlySalary() * 12;
      return yearlySalary;
   }
 
   // Calculate the appraisal amount of employee
   public double calculateAppraisal(EmployeeDetails employeeDetails){
      double appraisal=0;
      if(employeeDetails.getMonthlySalary() < 10000){
         appraisal = 500;
      }else{
         appraisal = 1000;
      }
      return appraisal;
   }
}
EmpBusinessLogic class is used for calculating
  • the yearly salary of employee.
  • the appraisal amount of employee.
TestEmployeeDetails.java which contains test cases to be tested.

import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class TestEmployeeDetails {
   EmpBusinessLogic empBusinessLogic =new EmpBusinessLogic();
   EmployeeDetails employee = new EmployeeDetails();

   //test to check appraisal
   @Test
   public void testCalculateAppriasal() {
      employee.setName("Rajeev");
      employee.setAge(25);
      employee.setMonthlySalary(8000);
      double appraisal= empBusinessLogic.calculateAppraisal(employee);
      assertEquals(500, appraisal, 0.0);
   }

   // test to check yearly salary
   @Test
   public void testCalculateYearlySalary() {
      employee.setName("Rajeev");
      employee.setAge(25);
      employee.setMonthlySalary(8000);
      double salary= empBusinessLogic.calculateYearlySalary(employee);
      assertEquals(96000, salary, 0.0);
   }
}
TestEmployeeDetails class is used for testing the methods of EmpBusinessLogic class. It
  • tests the yearly salary of the employee.
  • tests the appraisal amount of the employee.
Next, let's create a java class file name TestRunner.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestEmployeeDetails.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
} 
Compile the Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac EmployeeDetails.java 
EmpBusinessLogic.java TestEmployeeDetails.java TestRunner.java
Now run the Test Runner which will run test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output.
true
Assertion
Let's try to cover all of the above mentioned methods in an example. Create a java class file name TestAssertions.java in C:\ > JUNIT_WORKSPACE
import org.junit.Test;
import static org.junit.Assert.*;

public class TestAssertions {

   @Test
   public void testAssertions() {
      //test data
      String str1 = new String ("abc");
      String str2 = new String ("abc");
      String str3 = null;
      String str4 = "abc";
      String str5 = "abc";
      int val1 = 5;
      int val2 = 6;
      String[] expectedArray = {"one", "two", "three"};
      String[] resultArray =  {"one", "two", "three"};

      //Check that two objects are equal
      assertEquals(str1, str2);

      //Check that a condition is true
      assertTrue (val1 < val2);

      //Check that a condition is false
      assertFalse(val1 > val2);

      //Check that an object isn't null
      assertNotNull(str1);

      //Check that an object is null
      assertNull(str3);

      //Check if two object references point to the same object
      assertSame(str4,str5);

      //Check if two object references not point to the same object
      assertNotSame(str1,str3);

      //Check whether two arrays are equal to each other.
      assertArrayEquals(expectedArray, resultArray);
   }
}
Next, let's create a java class file name TestRunner.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)

import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner2 {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestAssertions.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
} 
Compile the Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac TestAssertions.java TestRunner.java
Now run the Test Runner which will run test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output.
true

Annotation:


Annotations are like meta-tags that you can add to you code and apply them to methods or in class. These annotation in JUnit gives us information about test methods , which methods are going to run before & after test methods, which methods run before & after all the methods, which methods or class will be ignore during execution.
List of annotations and their meaning in JUnit :
S.N.Annotation & Description
1@Test
The Test annotation tells JUnit that the public void method to which it is attached can be run as a test case.
2@Before
Several tests need similar objects created before they can run. Annotating a public void method with @Before causes that method to be run before each Test method.
3@After
If you allocate external resources in a Before method you need to release them after the test runs. Annotating a public void method with @After causes that method to be run after the Test method.
4@BeforeClass
Annotating a public static void method with @BeforeClass causes it to be run once before any of the test methods in the class.
5@AfterClass
This will perform the method after all tests have finished. This can be used to perform clean-up activities.
6@Ignore
The Ignore annotation is used to ignore the test and that test will not be executed.
Create a java class file name JunitAnnotation.java in C:\ > JUNIT_WORKSPACE to test annotation
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

public class JunitAnnotation {
 
   //execute before class
   @BeforeClass
   public static void beforeClass() {
      System.out.println("in before class");
   }

   //execute after class
   @AfterClass
   public static void  afterClass() {
      System.out.println("in after class");
   }

   //execute before test
   @Before
   public void before() {
      System.out.println("in before");
   }
 
   //execute after test
   @After
   public void after() {
      System.out.println("in after");
   }
 
   //test case
   @Test
   public void test() {
      System.out.println("in test");
   }
 
   //test case ignore and will not execute
   @Ignore
   public void ignoreTest() {
      System.out.println("in ignore test");
   }
}
Next, let's create a java class file name TestRunner.java in C:\ > JUNIT_WORKSPACE to execute annotaions
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(JunitAnnotation.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
} 
Compile the Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac JunitAnnotation.java TestRunner.java
Now run the Test Runner which will run test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output.
in before class
in before
in test
in after
in after class
true


This tutorial explains the execution procedure of methods in JUnit which means that which method is called first and which one after that. Here is the execution procedure of the JUint test API methods with the example.
Create a java class file name JunitAnnotation.java in C:\ > JUNIT_WORKSPACE to test annotation
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

public class ExecutionProcedureJunit {
 
   //execute only once, in the starting 
   @BeforeClass
   public static void beforeClass() {
      System.out.println("in before class");
   }

   //execute only once, in the end
   @AfterClass
   public static void  afterClass() {
      System.out.println("in after class");
   }

   //execute for each test, before executing test
   @Before
   public void before() {
      System.out.println("in before");
   }
 
   //execute for each test, after executing test
   @After
   public void after() {
      System.out.println("in after");
   }
 
   //test case 1
   @Test
   public void testCase1() {
      System.out.println("in test case 1");
   }

   //test case 2
   @Test
   public void testCase2() {
      System.out.println("in test case 2");
   }
}
Next, let's create a java class file name TestRunner.java in C:\ > JUNIT_WORKSPACE to execute annotaions
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(ExecutionProcedureJunit.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
} 
Compile the Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac ExecutionProcedureJunit.java TestRunner.java
Now run the Test Runner which will run test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output.
in before class
in before
in test case 1
in after
in before
in test case 2
in after
in after class
See the above output and this is how the JUnit execution procedure is.
  • First of all beforeClass() method execute only once
  • Lastly, the afterClass() method executes only once.
  • before() method executes for each test case but before executing the test case.
  • after() method executes for each test case but after the execution of test case
  • In between before() and after() each test case executes.
The test cases are executed using JUnitCore class. JUnitCore is a facade for running tests. It supports running JUnit 4 tests, JUnit 3.8.x tests, and mixtures. To run tests from the command line, run java org.junit.runner.JUnitCore <TestClass>. For one-shot test runs, use the static method runClasses(Class[]).
Following is the declaration for org.junit.runner.JUnitCore class:
public class JUnitCore extends java.lang.Object
Here we will see how can we execute the tests with the help of JUnitCore.

Create a Class

  • Create a java class to be tested say MessageUtil.java in C:\ > JUNIT_WORKSPACE
/*
* This class prints the given message on console.
*/
public class MessageUtil {

   private String message;

   //Constructor
   //@param message to be printed
   public MessageUtil(String message){
      this.message = message;
   }
      
   // prints the message
   public String printMessage(){
      System.out.println(message);
      return message;
   }   
}  

Create Test Case Class

  • Create a java test class say TestJunit.java.
  • Add a test method testPrintMessage() to your test class.
  • Add an Annotaion @Test to method testPrintMessage().
  • Implement the test condition and check the condition using assertEquals API of Junit.
Create a java class file name TestJunit.java in C:\ > JUNIT_WORKSPACE
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class TestJunit {
 
   String message = "Hello World"; 
   MessageUtil messageUtil = new MessageUtil(message);

   @Test
   public void testPrintMessage() {
      assertEquals(message,messageUtil.printMessage());
   }
}

Create Test Runner Class

Next, let's create a java class file name TestRunner.java in C:\ > JUNIT_WORKSPACE to execute Test case(s) which import the JUnitCore class and uses the runClasses() method which take the test class name as parameter.
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestJunit.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}   
Compile the Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
Now run the Test Runner which will run test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output.
Hello World
True
Test Suite

Test suite

Test suite means bundle a few unit test cases and run it together. In JUnit, both @RunWith and @Suiteannotation are used to run the suite test. This tutorial will show you an example having two TestJunit1 & TestJunit2 test classes to run together using Test Suite.

Create a Class

Create a java class to be tested say MessageUtil.java in C:\ > JUNIT_WORKSPACE
/*
* This class prints the given message on console.
*/
public class MessageUtil {

   private String message;

   //Constructor
   //@param message to be printed
   public MessageUtil(String message){
      this.message = message; 
   }

   // prints the message
   public String printMessage(){
      System.out.println(message);
      return message;
   }   

   // add "Hi!" to the message
   public String salutationMessage(){
      message = "Hi!" + message;
      System.out.println(message);
      return message;
   }   
}   

Create Test Case Classes

Create a java class file name TestJunit1.java in C:\ > JUNIT_WORKSPACE
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;

public class TestJunit1 {

   String message = "Robert"; 
   MessageUtil messageUtil = new MessageUtil(message);
   
   @Test
   public void testPrintMessage() { 
      System.out.println("Inside testPrintMessage()");    
      assertEquals(message, messageUtil.printMessage());     
   }
}
Create a java class file name TestJunit2.java in C:\ > JUNIT_WORKSPACE
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;

public class TestJunit2 {

   String message = "Robert"; 
   MessageUtil messageUtil = new MessageUtil(message);
 
   @Test
   public void testSalutationMessage() {
      System.out.println("Inside testSalutationMessage()");
      message = "Hi!" + "Robert";
      assertEquals(message,messageUtil.salutationMessage());
   }
}

Create Test Suite Class

  • Create a java class.
  • Attach @RunWith(Suite.class) Annotation with class.
  • Add reference to Junit test classes using @Suite.SuiteClasses annotation
Create a java class file name TestSuite.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
   TestJunit1.class,
   TestJunit2.class
})
public class JunitTestSuite {   
}   

Create Test Runner Class

Create a java class file name TestRunner.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(JunitTestSuite.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}   
Compile all java classes using javac
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit1.java 
TestJunit2.java JunitTestSuite.java TestRunner.java
Now run the Test Runner which will run test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output.
Inside testPrintMessage()
Robert
Inside testSalutationMessage()
Hi Robert
true

Sometimes it happens that our code is not ready and test case written to test that method/code will fail if run. The @Ignore annotation helps in this regards.
  • A test method annotated with @Ignore will not be executed.
  • If a test class is annotated with @Ignore then none of its test methods will be executed.
Now let's see @Ignore in action.

Create a Class

  • Create a java class to be tested say MessageUtil.java in C:\ > JUNIT_WORKSPACE
/*
* This class prints the given message on console.
*/
public class MessageUtil {

   private String message;

   //Constructor
   //@param message to be printed
   public MessageUtil(String message){
      this.message = message; 
   }

   // prints the message
   public String printMessage(){
      System.out.println(message);
      return message;
   }   

   // add "Hi!" to the message
   public String salutationMessage(){
      message = "Hi!" + message;
      System.out.println(message);
      return message;
   }   
}  

Create Test Case Class

  • Create a java test class say TestJunit.java.
  • Add a test methods testPrintMessage(),testSalutationMessage() to your test class.
  • Add an Annotaion @Ignore to method testPrintMessage().
Create a java class file name TestJunit.java in C:\ > JUNIT_WORKSPACE
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;

public class TestJunit {

   String message = "Robert"; 
   MessageUtil messageUtil = new MessageUtil(message);
   
   @Ignore
   @Test
   public void testPrintMessage() {
      System.out.println("Inside testPrintMessage()");
      message = "Robert";
      assertEquals(message,messageUtil.printMessage());
   }

   @Test
   public void testSalutationMessage() {
      System.out.println("Inside testSalutationMessage()");
      message = "Hi!" + "Robert";
      assertEquals(message,messageUtil.salutationMessage());
   }
}

Create Test Runner Class

Create a java class file name TestRunner.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestJunit.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}   
Compile the MessageUtil, Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
Now run the Test Runner which will not run testPrintMessage() test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output. testPrintMessage() test case is not tested.
Inside testSalutationMessage()
Hi!Robert
true
Now update TestJunit in C:\ > JUNIT_WORKSPACE to ignore all test cases. Add @Ignore at class level
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;

@Ignore
public class TestJunit {

   String message = "Robert"; 
   MessageUtil messageUtil = new MessageUtil(message);
     
   @Test
   public void testPrintMessage() {
      System.out.println("Inside testPrintMessage()");
      message = "Robert";
      assertEquals(message,messageUtil.printMessage());
   }

   @Test
   public void testSalutationMessage() {
      System.out.println("Inside testSalutationMessage()");
      message = "Hi!" + "Robert";
      assertEquals(message,messageUtil.salutationMessage());
   }
}
Compile the Test case using javac
C:\JUNIT_WORKSPACE>javac TestJunit.java
Keep your Test Runner unchanged as follows
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestJunit.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}
Now run the Test Runner which will not run any test case defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output. No test case is tested.
true

Junit provides a handy option of Timeout. If a test case takes more time than specified number of milliseconds then Junit will automatically mark it as failed. The timeout parameter is used along with @Test annotation. Now let's see @Test(timeout) in action.

Create a Class

  • Create a java class to be tested say MessageUtil.java in C:\ > JUNIT_WORKSPACE.
  • Add a infinite while loop inside printMessage() method.
/*
* This class prints the given message on console.
*/
public class MessageUtil {

   private String message;

   //Constructor
   //@param message to be printed
   public MessageUtil(String message){
      this.message = message; 
   }

   // prints the message
   public void printMessage(){
      System.out.println(message);
      while(true);
   }   

   // add "Hi!" to the message
   public String salutationMessage(){
      message = "Hi!" + message;
      System.out.println(message);
      return message;
   }   
}   

Create Test Case Class

  • Create a java test class say TestJunit.java.
  • Add timeout of 1000 to testPrintMessage() test case.
Create a java class file name TestJunit.java in C:\ > JUNIT_WORKSPACE
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;

public class TestJunit {

   String message = "Robert"; 
   MessageUtil messageUtil = new MessageUtil(message);
   
   @Test(timeout=1000)
   public void testPrintMessage() { 
      System.out.println("Inside testPrintMessage()");     
      messageUtil.printMessage();     
   }

   @Test
   public void testSalutationMessage() {
      System.out.println("Inside testSalutationMessage()");
      message = "Hi!" + "Robert";
      assertEquals(message,messageUtil.salutationMessage());
   }
}

Create Test Runner Class

Create a java class file name TestRunner.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestJunit.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}   
Compile the MessageUtil, Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
Now run the Test Runner which will run test cases defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output. testPrintMessage() test case will mark unit testing failed.
Inside testPrintMessage()
Robert
Inside testSalutationMessage()
Hi!Robert
testPrintMessage(TestJunit): test timed out after 1000 milliseconds
false

Junit provides a option of tracing the Exception handling of code. You can test the code whether code throws desired exception or not. The expected parameter is used along with @Test annotation. Now let's see @Test(expected) in action.

Create a Class

  • Create a java class to be tested say MessageUtil.java in C:\ > JUNIT_WORKSPACE.
  • Add a error condition inside printMessage() method.
/*
* This class prints the given message on console.
*/
public class MessageUtil {

   private String message;

   //Constructor
   //@param message to be printed
   public MessageUtil(String message){
      this.message = message; 
   }

   // prints the message
   public void printMessage(){
      System.out.println(message);
      int a =0;
      int b = 1/a;
   }   

   // add "Hi!" to the message
   public String salutationMessage(){
      message = "Hi!" + message;
      System.out.println(message);
      return message;
   }   
}   

Create Test Case Class

  • Create a java test class say TestJunit.java.
  • Add expected exception ArithmeticException to testPrintMessage() test case.
Create a java class file name TestJunit.java in C:\ > JUNIT_WORKSPACE
import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;

public class TestJunit {

   String message = "Robert"; 
   MessageUtil messageUtil = new MessageUtil(message);
   
   @Test(expected = ArithmeticException.class)
   public void testPrintMessage() { 
      System.out.println("Inside testPrintMessage()");     
      messageUtil.printMessage();     
   }

   @Test
   public void testSalutationMessage() {
      System.out.println("Inside testSalutationMessage()");
      message = "Hi!" + "Robert";
      assertEquals(message,messageUtil.salutationMessage());
   }
}

Create Test Runner Class

Create a java class file name TestRunner.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestJunit.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}   
Compile the MessageUtil, Test case and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
Now run the Test Runner which will run test cases defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output. testPrintMessage() test case will be passed.
Inside testPrintMessage()
Robert
Inside testSalutationMessage()
Hi!Robert
true

Junit 4 has introduced a new feature Parameterized tests.Parameterized tests allow developer to run the same test over and over again using different values. There are five steps, that you need to follow to create Parameterized tests.
  • Annotate test class with @RunWith(Parameterized.class)
  • Create a public static method annotated with @Parameters that returns a Collection of Objects (as Array) as test data set.
  • Create a public constructor that takes in what is equivalent to one "row" of test data.
  • Create an instance variable for each "column" of test data.
  • Create your tests case(s) using the instance variables as the source of the test data.
The test case will be invoked once per each row of data. Let's see Parameterized tests in action.

Create a Class

  • Create a java class to be tested say PrimeNumberChecker.java in C:\ > JUNIT_WORKSPACE.
public class PrimeNumberChecker {
   public Boolean validate(final Integer primeNumber) {
      for (int i = 2; i < (primeNumber / 2); i++) {
         if (primeNumber % i == 0) {
            return false;
         }
      }
      return true;
   }
}

Create Parameterized Test Case Class

  • Create a java test class say PrimeNumberCheckerTest.java.
Create a java class file name PrimeNumberCheckerTest.java in C:\ > JUNIT_WORKSPACE
import java.util.Arrays;
import java.util.Collection;
 
import org.junit.Test;
import org.junit.Before;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;

@RunWith(Parameterized.class)
public class PrimeNumberCheckerTest {
   private Integer inputNumber;
   private Boolean expectedResult;
   private PrimeNumberChecker primeNumberChecker;

   @Before
   public void initialize() {
      primeNumberChecker = new PrimeNumberChecker();
   }

   // Each parameter should be placed as an argument here
   // Every time runner triggers, it will pass the arguments
   // from parameters we defined in primeNumbers() method
   public PrimeNumberCheckerTest(Integer inputNumber, 
      Boolean expectedResult) {
      this.inputNumber = inputNumber;
      this.expectedResult = expectedResult;
   }

   @Parameterized.Parameters
   public static Collection primeNumbers() {
      return Arrays.asList(new Object[][] {
         { 2, true },
         { 6, false },
         { 19, true },
         { 22, false },
         { 23, true }
      });
   }

   // This test will run 4 times since we have 5 parameters defined
   @Test
   public void testPrimeNumberChecker() {
      System.out.println("Parameterized Number is : " + inputNumber);
      assertEquals(expectedResult, 
      primeNumberChecker.validate(inputNumber));
   }
}

Create Test Runner Class

Create a java class file name TestRunner.java in C:\ > JUNIT_WORKSPACE to execute Test case(s)
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(PrimeNumberCheckerTest.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}   
Compile the PrimeNumberChecker, PrimeNumberCheckerTest and Test Runner classes using javac
C:\JUNIT_WORKSPACE>javac PrimeNumberChecker.java PrimeNumberCheckerTest.java
TestRunner.java
Now run the Test Runner which will run test cases defined in provided Test Case class.
C:\JUNIT_WORKSPACE>java TestRunner
Verify the output.
Parameterized Number is : 2
Parameterized Number is : 6
Parameterized Number is : 19
Parameterized Number is : 22
Parameterized Number is : 23
true

Following are the JUnit extensions
  • Cactus
  • JWebUnit
  • XMLUnit
  • MockObject

Cactus

Cactus is a simple test framework for unit testing server-side java code (Servlets, EJBs, Tag Libs, Filters). The intent of Cactus is to lower the cost of writing tests for server-side code. It uses JUnit and extends it. Cactus implements an in-container strategy, meaning that tests are executed inside the container.
Cactus Ecosystem is made of several components:
  • Cactus Framework is the heart of Cactus. It is the engine that provides the API to write Cactus tests.
  • Cactus Integration Modules are front ends and frameworks that provide easy ways of using the Cactus Framework (Ant scripts, Eclipse plugin, Maven plugin).
Here is the code example how cactus can be used.
import org.apache.cactus.*;
import junit.framework.*;

public class TestSampleServlet extends ServletTestCase {
   @Test
   public void testServlet() {
      // Initialize class to test
      SampleServlet servlet = new SampleServlet();

      // Set a variable in session as the doSomething()
      // method that we are testing 
      session.setAttribute("name", "value");

      // Call the method to test, passing an 
      // HttpServletRequest object (for example)
      String result = servlet.doSomething(request);

      // Perform verification that test was successful
      assertEquals("something", result);
      assertEquals("otherValue", session.getAttribute("otherName"));
   }
}

JWebUnit

JWebUnit is a Java-based testing framework for web applications. It wraps existing testing frameworks such as HtmlUnit and Selenium with a unified, simple testing interface to allow you to quickly test the correctness of your web applications.
JWebUnit provides a high-level Java API for navigating a web application combined with a set of assertions to verify the application's correctness. This includes navigation via links, form entry and submission, validation of table contents, and other typical business web application features.
The simple navigation methods and ready-to-use assertions allow for more rapid test creation than using only JUnit or HtmlUnit. And if you want to switch from HtmlUnit to other plugins such as Selenium (available soon), there is no need to rewrite your tests.
Here is the sample code
import junit.framework.TestCase;
import net.sourceforge.jwebunit.WebTester;

public class ExampleWebTestCase extends TestCase {
   private WebTester tester;
   
   public ExampleWebTestCase(String name) {
        super(name);
        tester = new WebTester();
   }
   //set base url
   public void setUp() throws Exception {
       getTestContext().setBaseUrl("http://myserver:8080/myapp");
   }
   // test base info
   @Test
   public void testInfoPage() {
       beginAt("/info.html");
   }
}

XMLUnit

XMLUnit provides a single JUnit extension class, XMLTestCase, and a set of supporting classes that allow assertions to be made about:
  • The differences between two pieces of XML (via Diff and DetailedDiff classes)
  • The validity of a piece of XML (via Validator class)
  • The outcome of transforming a piece of XML using XSLT (via Transform class)
  • The evaluation of an XPath expression on a piece of XML (via classes implementing the XpathEngine interface)
  • Individual nodes in a piece of XML that are exposed by DOM Traversal (via NodeTest class)
Lets say we have two pieces of XML that we wish to compare and assert that they are equal. We could write a simple test class like this:
import org.custommonkey.xmlunit.XMLTestCase;

public class MyXMLTestCase extends XMLTestCase {

   // this test method compare two pieces of the XML
   @Test
   public void testForXMLEquality() throws Exception {
      String myControlXML = "<msg><uuid>0x00435A8C</uuid></msg>";
      String myTestXML = "<msg><localId>2376</localId></msg>";
      assertXMLEqual("Comparing test xml to control xml",
      myControlXML, myTestXML);
   }
}

MockObject

In a unit test, mock objects can simulate the behavior of complex, real (non-mock) objects and are therefore useful when a real object is impractical or impossible to incorporate into a unit test.
The common coding style for testing with mock objects is to:
  • Create instances of mock objects
  • Set state and expectations in the mock objects
  • Invoke domain code with mock objects as parameters
  • Verify consistency in the mock objects
  • Below is the example of MockObject using Jmock.
    import org.jmock.Mockery;
    import org.jmock.Expectations;
    
    class PubTest extends TestCase {
       Mockery context = new Mockery();
       public void testSubReceivesMessage() {
          // set up
          final Sub sub = context.mock(Sub.class);
    
          Pub pub = new Pub();
          pub.add(sub);
        
          final String message = "message";
          
          // expectations
          context.checking(new Expectations() {
             oneOf (sub).receive(message);
          });
    
          // execute
          pub.publish(message);
          
          // verify
          context.assertIsSatisfied();
       }
    }


No comments:

Post a Comment