This is a presentation that I did for using junit test.
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());
HSQLDB
HSQLDB stands for "Hyper Structured Query Language Database". It is a relational database management system written in Java. It offers a fast, small database engine which offers both in-memory and disk-based tables. Embedded and server modes are available.
Instead of connecting to the actual database, JUnit can use HSQLDB for tests related to database actions.
Example: LocationDaoTest.java. This test class extends
AbstractTransactionalDataSourceSpringContextTests. This is from Spring. It is a subclass of TestCase and offers features such as transaction management and bean injection.
Resources
- http://java.sun.com/developer/Books/javaprogramming/ant/ant_chap04.pdf
- http://www.ibm.com/developerworks/java/library/j-easymock/index.html
- http://www.ibm.com/developerworks/java/library/j-junit4/index.html
- http://www.methodsandtools.com/tools/tools.php?junit