The presentation contains a definition and survey of the benefits of Unit Testing, and a little coding example to get the feeling of Unit Testing using JUnit, EasyMock and XMLUnit.
19. Our example: UML Class Diagram We have to implement and test the CachedBookService class
20. Constructor implementation of CachedBookService public class CachedBookService implements IBookService { private IBookService remoteBookService ; public CachedBookService(IBookService bookService){ if(bookService == null){ throw new IllegalArgumentException(); } this.remoteBookService = bookService; } public IBookService getRemoteBookService() { return remoteBookService; } public IBook getBook(String code) throws NoSuchElementException { // implementation left out for the moment throw new NotImplementedException(); } } Ok, let's test the constructor
21.
22.
23.
24. Testing object state after constructor import static org.junit.Assert.*; import org.junit.Test; public class CachedBookServiceTest { @Test public void testConstructor () { // anonymous class to test in isolation CachedBookService constructor IBookService bookServiceParameter = new IBookService(){ public IBook getBook(String code) throws NoSuchElementException { return null; } }; CachedBookService cachedBookService = new CachedBookService(bookServiceParameter); assertNotNull ("Assert not null", cachedBookService.getRemoteBookService()); /* 3 identical ways to test the reference value: */ assertTrue ("Assert same reference", bookServiceParameter == cachedBookService.getRemoteBookService()); // assertSame ("Assert same reference", bookServiceParameter, cachedBookService.getRemoteBookService()); // assertEquals (“Assert same reference”, bookServiceParameter, cachedBookService.getRemoteBookService()) }
25. Testing exception is thrown // CachedBookServiceTest.java @Test(expected=IllegalArgumentException.class) public void testConstructorWithNullArg () { // should throw IllegaArgumentException with null arg new CachedBookService( null ); } }
27. Now let's implement getBook() method public class CachedBookService implements IBookService { private IbookService remoteBookService; private Map<String, IBook> cache; public CachedBookService(IBookService bookService){ if(bookService == null){ throw new IllegalArgumentException(); } this.remoteBookService = bookService; this.cache = new HashMap<String, IBook>(); } public IBook getBook(String code) throws NoSuchElementException { IBook ibook = cache.get(code); if(ibook != null){ return ibook; }else{ IBook result = this.remoteBookService.getBook(code); this.cache.put(code, result); return result; } } Ok, let's test getBook()
28.
29.
30.
31.
32.
33. Testing getBook() - 1 st test method @Test public void testGetBook () { // (1) create the mock for the collaborating object IBookService mockBookService = EasyMock.createMock(IBookService.class); // a mock with no behaviour as return value of getBook() IBook mockBook = EasyMock.createMock(IBook.class); // (2) record the expected behaviour EasyMock.expect(mockBookService.getBook("id123")).andReturn(mockBook); // (3) switch the mock to replay state EasyMock.replay(mockBookService); CachedBookService cachedBookService = new CachedBookService(mockBookService); // (4) perform the call to the class under test which interacts with the mock IBook result = cachedBookService.getBook("id123"); assertSame(“Assert same reference”, mockBook, result); // (5) verify the mock has been used as expected EasyMock.verify(mockBookService); }
34. Testing getBook() - 2 nd test method @Test public void testGetBookTwoDifferentCodes () { // (1) create the mock for the collaborating object IBookService mockBookService = EasyMock.createMock(IBookService.class); // a mock with no behaviour as return value of getBook() IBook mockBook = EasyMock.createMock(IBook.class); IBook mockBook2 = EasyMock.createMock(IBook.class); // (2) record two expected calls EasyMock.expect(mockBookService.getBook("id123")).andReturn(mockBook); EasyMock.expect(mockBookService.getBook("id456")).andReturn(mockBook2); // (3) switch the mock to replay state EasyMock.replay(mockBookService); CachedBookService cachedBookService = new CachedBookService(mockBookService); // (4) perform the call to the class under test which interacts with the mock IBook result = cachedBookService.getBook("id123"); assertSame(“Assert same reference”, mockBook, result); IBook result2 = cachedBookService.getBook("id456"); assertSame(“Assert same reference”, mockBook2, result2); // (5) verify the mock has been used as expected EasyMock.verify(mockBookService); }
35. Testing getBook() - 3 rd test method @Test public void testGetSameBookTwoTimes () { IBookService mockBookService = EasyMock.createMock(IBookService.class); IBook mockBook = EasyMock.createMock(IBook.class); // record only one call EasyMock.expect(mockBookService.getBook("id123")).andReturn(mockBook); EasyMock.replay(mockBookService); CachedBookService cachedBookService = new CachedBookService(mockBookService); IBook result = cachedBookService.getBook("id123"); assertSame(mockBook, result); IBook secondResult = cachedBookService.getBook("id123"); assertSame(result, secondResult); EasyMock.verify(mockBookService); }
38. IBookXmlSerializerImpl public class IBookXmlSerializerImpl implements IBookXmlSerializer { public String serialize(IBook book) { StringBuilder sb = new StringBuilder(""); sb.append("<book>"); sb.append(" <code>" + book.getCode() + "</code>"); sb.append(" <title>" + book.getTitle() + "</title>"); sb.append(" <author>" + book.getAuthor() + "</author>"); sb.append("</book>"); return sb.toString(); } } Ok, let's test serialize()
39.
40.
41. IbookXmlSerializerTest - Part 1 import org.custommonkey.xmlunit.XMLTestCase; public class IBookXmlSerializerImplTest { private IBookXmlSerializer serializer; private IBook book; private XMLTestCase xmlTestCase; @Before public void setUp() throws Exception { this.serializer = new IBookXmlSerializerImpl(); this.book = EasyMock.createMock(IBook.class); this.xmlTestCase = new XMLTestCase(); } // .... The method annotated with @Before is executed before every @Test method execution
42. IbookXmlSerializerTest - Part 2 @Test public void testSerialize() throws Exception { final String code = "id1"; EasyMock.expect(this.book.getCode()).andReturn(code); final String title = "Unit Testing"; EasyMock.expect(this.book.getTitle()).andReturn(title); final String author = "Mario Rossi"; EasyMock.expect(this.book.getAuthor()).andReturn(author); // switch to replay state EasyMock.replay(this.book); String xml = this.serializer.serialize(book); this.xmlTestCase.assertXpathExists("/book", xml); this.xmlTestCase.assertXpathEvaluatesTo(code, "/book/code", xml); this.xmlTestCase.assertXpathEvaluatesTo(title, "/book/title", xml); this.xmlTestCase.assertXpathEvaluatesTo(author, "/book/author", xml); // verify mock EasyMock.verify(this.book); }