Unit Testing Using Junit: Inf5750/9750 - Lecture 4 (Part Ii)
Unit Testing Using Junit: Inf5750/9750 - Lecture 4 (Part Ii)
using JUnit
INF5750/9750 - Lecture 4 (Part II)
Problem area
● Code components must be tested!
○ Confirms that your code works
● Components must be tested in isolation
○ A functional test can tell you that a bug exists in the
implementation
○ A unit test tells you where the bug is located
Test failure!
Component A But where
is the bug?
<using> <using>
Component B Component C
Example: The Calculator
public interface Calculator
{
int add( int number1, int number2 );
if ( result != 15 )
{
System.out.println( ”Wrong result: ” + result );
}
}
}
The preferred solution
● Use a unit testing framework like JUnit
○ A unit is the smallest testable component in an
application
○ A unit is in most cases a method
○ A unit does not depend on other components which
are not unit tested themselves
○ Focus on whether a method is following its API
contract
<using> <using>
● Class-scoped fixture
○ Identified by @BeforeClass and @AfterClass annotations
○ Useful for setting up expensive resources, but be careful…
● Ignored tests
○ Identified by @Ignore annotation
○ Useful for slow tests and tests failing for reasons beyond you
● Timed tests
○ Identified by providing a parameter @Test(timeout=500)
○ Useful for benchmarking, network, deadlock testing
Test fixtures
● Tests may require common resources to be set up
○ Complex data structures
○ Database connections
TestCase
lifecycle
setUp() testXXX() tearDown()
JUnit Calculator test
import static junit.framework.Assert.*;
Static import of Assert
public class CalculatorTest
{
Calculator calculator;
Fixture
@Before
public void before()
{
Fixture calculator = new DefaultCalculator();
}
@Test
public void addTest()
{
Use assertEquals to
int sum = calculator.add( 8, 7 );
verify output assertEquals( sum, 15 );
}
@Test
public void multiplyTest()
{
}
}
Example: The EventDAO
public class Event()
Event object {
private int id;
private String title;
private Date date;
// constructors
// get and set methods
}
@Test
public void saveEvent()
Test identified by the @Test {
int id = eventDAO.saveEvent( event );
annotation. Test signature is
equal to method signature.
event = eventDAO.getEvent( id );
TestCase
<inherits>
EventDAOTest
Assert methods
Method Description
assertArrayEquals ( Object[], Object[] ) Asserts that all elements in the two arrays are equal
assertSame( Object, Object ) Asserts that two references refer to the same object.
assertNotSame( Object, Object ) Asserts that two references do not refer to the same object.
fail( String ) Asserts that a test fails, and prints the given message.
Assert in EventDAOTest
@Test
public void testSaveEvent()
{
Asserts that the saved object is int id = eventDAO.saveEvent( event );
event = eventDAO.getEvent( id );
equal to the retrieved object
assertEquals( id, event.getId() );
assertEquals( ”U2 concert”, event.getTitle() );
}
assertThat(theBiscuit, equalTo(myBiscuit));
assertThat(theBiscuit, is(equalTo(myBiscuit))); is - syntactic sugar - all 3 statements are same
assertThat(theBiscuit, is(myBiscuit));
<dependency>
<groupId>junit</groupId>
Add dependency <artifactId>junit</artifactId>
to POM to put <version>4.11</version>
JUnit on the classpath <scope>test</scope>
</dependency>
Server-side Client-side
standaloneSetup(new BaseController()) {
.alwaysExpect(status().isOk())
.alwaysExpect(content().contentType("application/json;charset=UTF-8"))
.build()
}
Best practices
● One unit test for each tested method
○ Makes debugging easier
○ Easier to maintain
● Choose descriptive test method names
○ TestCase: Use the testXXX naming convention
○ Annotations: Use the method signature of the tested method
● Automate your test execution
○ If you add or change features, the old ones must still work
○ Also called regression testing
● Test more than the ”happy path”
○ Out-of-domain values
○ Boundary conditions
Advantages of unit testing
● Improves debugging
○ Easy to track down bugs
● Facilitates refactoring
○ Verifies that existing features still work while changing the code
structure
● Enables teamwork
○ Lets you deliver tested components without waiting for the
whole application to finish
● Promotes object oriented design
○ Requires your code to be divided in small, re-usable units
● Serving as developer documentation
○ Unit tests are samples that demonstrates usage of the API
Mocking Tests...