Showing posts with label Junit interview question.Best Practices to write JUnit test cases in Java. Show all posts
Showing posts with label Junit interview question.Best Practices to write JUnit test cases in Java. Show all posts

Junit tutorial | Best Practices to write JUnit test cases in Java | Junit interview question

Introduction to JUnit Test

Uses
A framework for unit test. Used mainly to test individual classes and methods.

JUnit Library
In maven pom.xml:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>

The scope is "test". So the junit.jar will not be packaged into the application for deployment.
Configure Maven for Running JUnit
In maven pom.xml:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!--<skipTests>true</skipTests>-->
<testFailureIgnore>false</testFailureIgnore>
</configuration>
</plugin>

If skipTests is true, no unit tests will be run.
If testFailureIgnore is true, the tests will be run and the build maven will succeed even if some tests fail.
If testFailureIgnore is false, the tests will be run and build will fail if a test fails.

The test results will go to the directory:
project_base_directory\target\surefire-reports

Traditional JUnit Test
The test class must extend the JUnit class TestCase or its subclasses.

    Use setUp() to initialize resources.
    Use tearDown() to release resources
    Every test method must start with the lowercase "test".

The lifecycle of a TestCase
The lifecycle of a TestCase used by the JUnit framework is as follows:

    Execute setUp().
    Call a test-prefixed method.
    Execute tearDown().
    Repeat these steps for each test method. This will occur even if setUp() or tearDown() throws an exception

Notes:
If setUp() throws an Exception, the test method and tearDown() will not be executed.
If the test method fails and throws an error or exception, tearDown() will still be executed.

Utility Methods from Assert

    assertTrue(String message, boolean condition)
    assertFalse(String message, boolean condition)
    fail(String message)
    assertEquals(String message, Object expected, Object actual)
    assertEquals(String message, String expected, String actual)
    assertEquals(String message, double expected, double actual, double delta)
    assertEquals(String message, int expected, int actual)
    assertSame(String message, Object expected, Object actual)
    assertNotNull(String message, Object object)
    assertNull(String message, Object object)

See the class junit.framework.Assert for more methods.

A Sample Class for Testing

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Sound {
 private Map<String, String> voicemap = new HashMap<String, String>() {
  {
   put("bee", "buzz");
   put("cow", "moo");
   put("dog", "woof");
   put("cat", "meow");
   put("snake", "hiss");
   put("bird", "chir");
   put("goose", "honk");
  }
 };

 public String speak(String animal) throws Exception {
  if (animal == null) {
   throw new Exception("animial is not specified.");
  }
  String name = animal.toLowerCase();
  Set<String> animals = voicemap.keySet();
  if (!animals.contains(name)) {
   throw new Exception("not implemented yet for this animal.");
  }
  return voicemap.get(name);
 }

 public String yell(String animal) throws Exception {
  String sound = speak(animal);
  return sound.toUpperCase();
 }
}


A Sample JUnit Test Class

import junit.framework.TestCase;

public class SoundTest extends TestCase {

/* This is for demo only. In real life, you won’t need to initialize a simple object such as Sound here. The objects that need to be initialized  in the setUp() method are usually more complex resources such as database connection.
*/
 private Sound sound = null;

 @Override
 protected void setUp() throws Exception {
  super.setUp();
  sound = new Sound(); 
 }

 @Override
 protected void tearDown() throws Exception {
  sound = null;
  super.tearDown();
 }

 public void testSpeak() throws Exception {
  String beeSound = sound.speak("bee");
  assertEquals("buzz", beeSound);
  try {
   String temp = sound.speak("fish");
   fail("Failed for fish. This statemente should not have been executed");
  } catch (Exception e) {
   return; // excepted
  }
 }

 public void testYell() {
  try {
   String gooseYell = sound.yell("goose");
   assertEquals("The sound of goose is not right", "HONK", gooseYell);
  } catch (Exception e) {
   fail("Test failed. This statement should not have been reached.");
  }
 }
}


Run JUnit in Eclipse


Run JUnit Test On CommandLine
JUnit provides the TestRunner classes for running all the tests. The two most popular test runners are a text-based one, junit.textui.TestRunner, and a Swing-based one, junit.swingui.TestRunner

Example:
java junit.textui.TestRunner org.example.SampleTest

TestSuite
JUnit tests can be grouped together by using the TestSuite class.
Example:

import junit.framework.Test;
import junit.framework.TestSuite;

public class GroupTests extends TestSuite {
      static public Test suite() {
            TestSuite suite = new TestSuite();
             suite.addTestSuite(SimpleTest1.class);
             suite.addTestSuite(SimpleTest2.class);
             return suite;
    }
}


When this test is run, both SimpleTest1 and SimpleTest2 will be invoked.

Junit Test Using Annotation in JUnit4

    No need to extend the class TestCase
    No need to use setUp() or tearDown(). Use @Before and @After instead.
    The test method name does not need to start with "test". But you need to put the @Test annotation before each test method.
    Use @Test(expected = YourException.class) to test exception
    Can use @Test(timeout = ?) for performance testing. Here "?" is time in milliseconds.
    Can use @Ignore to ignore a test

Example Using Annotation

import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

public class SoundAnnotationTest {

/** This is for demo only. In real life, you won’t need to initialize a simple object such as Sound here. The objects that need to be initialized  in the @Before method are usually more complex resources such as database connection.
*/
 private Sound sound = null;

 /**
  * The method name does not have to be setUp. You can have multiple such
  * methods with the "Before" annotattion, each of which is run before each
  * test
  */
 @Before
 public void setUp() {
  sound = new Sound();
 }

 /**
  * The method name does not have to be tearDown. You can have multiple such
  * methods with teh "After" annotation, each of which is run after each
  * test.
  */
 @After
 public void tearDown() {
  sound = null;

 }

 @Test
 public void speak() {
  try {
   String beeSound = sound.speak("bee");
   Assert.assertEquals("buzz", beeSound);
  } catch (Exception e) {
   Assert.fail("Test failed.");
  }

  try {
   sound.speak("fish");
   Assert.fail("Failed for fish. This statemente should not have been executed");
  } catch (Exception e) {
   return; // excepted
  }
 }

 @Test
 public void testYell() {
  try {
   String gooseYell = sound.yell("goose");
   Assert.assertEquals("The sound of goose is not right", "HONK",
     gooseYell);
  } catch (Exception e) {
   Assert.fail("Test failed. This statement should not have been reached.");
  }
 }

 @Test(expected = Exception.class)
 // IndexOutOfBoundsException.class
 public void testFish() throws Exception {
  sound.speak("fish");
 }

 @Test(timeout = 700)
 public void testPerformance() throws Exception {
  Thread.currentThread().sleep(600);
 }

 @Ignore
 public void foo() throws Exception {
  for (int i = 0; i < 10; i++) {
   // no-op
  }
 }
}


Use EasyMock in JUnit

    Create Mock object using EasyMock.createMock
    Mock expected results using EasyMock's expect and the andReturn()/andThrow() method
    You can use andReturn to return the value you want.
    You can use andThrow to throw any kind of exception you like.
    Call the EasyMock replay() method.
    Do test and check results.


Example Using EasyMock

(MyServiceEndpointTest)
fooServiceMock = createMock(FooService.class);
barServiceMock = createMock(BarService.class);
endPoint = new MarshallingCommonServiceEndpoint(barServiceMock,
    fooServiceMock);
expect(barServiceMock.getSomeInput(arg1, arg2)).andReturn(Boolean.TRUE);
replay(barServiceMock);
GetBarResponse response = endPoint.getBar(request);
assertTrue("Invalid status", response.isStatus());