Saturday, December 21, 2013

Lazyrecords - Data Source Access Framework from Google Code


Overview:
This article looks at Lazyrecords, a Google Code framework for accessing data repositories using functional programming. Lazyrecords yields faster performance via functional programming style.

I will try to keep the content simple and straight by presenting the basic CRUD operations using a simple Unit tests that involves storing, retrieving, updating and deleting Book entities.

You can learn more about the framework here.

The sample code for this article can be found here.

Project Structure:

 org.fazlan.lazyrecords  
 ├── pom.xml  
 └── src  
   ├── main  
   │   └── java  
   │     └── org  
   │       └── fazlan  
   │         └── lazyrecords  
   │           └── book  
   │             └── Books.java  
   └── test  
     └── java  
       └── org  
         └── fazlan  
           └── lazyrecords  
             ├── book  
             │   ├── BooksRecordTest.java  
             │   └── H2BooksRecordTest.java  
             └── util  
               └── DataSourceObjectMother.java  

Step 1: Creating the Project

 mvn archetype:generate -DartifactId=org.fazlan.lazyrecords -DgroupId=org.fazlan.lazyrecords -Dversion=1.0-SNAPSHOT -DinteractiveMode=false  

Step 2: Updating the Maven dependencies
 <?xml version="1.0" encoding="UTF-8"?>  
 <project xmlns="http://maven.apache.org/POM/4.0.0"  
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
   <modelVersion>4.0.0</modelVersion>  
   <groupId>org.fazlan.lazyrecords</groupId>  
   <artifactId>lazyrecords</artifactId>  
   <version>1.0-SNAPSHOT</version>  
   <properties>  
     <h2.version>1.3.159</h2.version>  
     <lazyrecords.version>272</lazyrecords.version>  
     <testng.version>6.8</testng.version>  
     <totallylazy.version>1165</totallylazy.version>  
     <hamcrest.version>1.3.RC2</hamcrest.version>  
   </properties>  
   <dependencies>  
     <dependency>  
       <groupId>com.h2database</groupId>  
       <artifactId>h2</artifactId>  
       <version>${h2.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>com.googlecode.lazyrecords</groupId>  
       <artifactId>lazyrecords</artifactId>  
       <version>${lazyrecords.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>com.googlecode.totallylazy</groupId>  
       <artifactId>totallylazy</artifactId>  
       <version>${totallylazy.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.hamcrest</groupId>  
       <artifactId>hamcrest-core</artifactId>  
       <version>${hamcrest.version}</version>  
       <scope>test</scope>  
     </dependency>  
     <dependency>  
       <groupId>org.hamcrest</groupId>  
       <artifactId>hamcrest-library</artifactId>  
       <version>${hamcrest.version}</version>  
       <scope>test</scope>  
     </dependency>  
     <dependency>  
       <groupId>org.testng</groupId>  
       <artifactId>testng</artifactId>  
       <version>${testng.version}</version>  
       <scope>test</scope>  
     </dependency>  
   </dependencies>  
 </project>  

Step 3: Creating the Definition and the Keywords for the Book Entity

The definition is represented in the form of an Interface with the fields as Keywords as shown,

 package org.fazlan.lazyrecords.book; 
 
 import com.googlecode.lazyrecords.Definition;  
 import com.googlecode.lazyrecords.Keyword;  
 import java.math.BigDecimal;  
 import java.net.URI;  
 import java.util.UUID;  
 import static com.googlecode.lazyrecords.Grammar.definition;  
 import static com.googlecode.lazyrecords.Grammar.keyword;  

 public interface Books extends Definition {  

   Books BOOKS = definition(Books.class);
  
   Keyword<URI> isbn = keyword("isbn", URI.class);  
   Keyword<String> title = keyword("title", String.class);  
   Keyword<Boolean> inPrint = keyword("inPrint", Boolean.class);  
   Keyword<UUID> uuid = keyword("uuid", UUID.class);  
   Keyword<BigDecimal> rrp = keyword("rrp", BigDecimal.class);  
 }  

Step 4: Configuring the Connection, Creating the Records and Setting-up Initial Data.
The Framework allows you to access different types of data repositories such as JDBC, XML, Lucene and In-Memory. During this example, we will be accessing an In-Memory H2 database.

 . . .

 import static org.fazlan.lazyrecords.util.DataSourceObjectMother.getH2Connection;

 @Test  
 public class BooksRecordTest {  
   . . .  
   protected Records records;  
   protected Connection connection; 
 
   @BeforeMethod  
   public void beforeEachMethodSetupRecords() throws Exception {  
     this.connection = getH2Connection();  
     createRecords();  
     setupData();  
   }  

   @AfterMethod  
   public void afterEachMethodCleanUp() throws Exception {  
     close(records);  
     safeClose(connection);  
   }  
   . . .  
 }  

Creating the Records to Use the Newly Created Connection to the H2 Database

 @Test  

 public class BooksRecordTest {  
   . . .  

   private void createRecords() throws SQLException {  
     records = DataSourceObjectMother.createRecords(connection);  
   }  

   . . .  
 }  

Records acts as the interface between your application and the data repository ( think of it as the Session in Hibernate). The following code is to initialising the Records with some basic configuration.

 public class DataSourceObjectMother {  
   
   . . .  
   
   public static Records createRecords(Connection connection) throws SQLException {  
     SqlGrammar grammar = new AnsiSqlGrammar();  
     SqlRecords sqlRecords = sqlRecords(connection, grammar);  
     return new SchemaGeneratingRecords(sqlRecords, new SqlSchema(sqlRecords, grammar));  
   }
  
   private static SqlRecords sqlRecords(Connection connection, SqlGrammar grammar) {  
     return new SqlRecords(  
         connection, new SqlMappings(), grammar,  
         loggers(new MemoryLogger(), new PrintStreamLogger(new PrintStream(streams(System.out, new ByteArrayOutputStream()))))  
     );  
   }  
 }  

We tell the framework to create a database schema based on the Books Definition and set the default SQL grammar.

You can read more about these configuration here.

Setting-up the Initial Data ( Inserting Book Records to the Database)

 . . .  
 import static org.fazlan.lazyrecords.book.Books.*;  
 . . .  
 @Test  
 public class BooksRecordTest {  
   public static final URI zenIsbn = uri("urn:isbn:0099322617");  
   public static final URI godelEsherBach = uri("urn:isbn:0140289208");  
   public static final URI cleanCode = uri("urn:isbn:0132350882");  
   public static final UUID zenUuid = randomUUID();  
   . . .  
   private void setupData() {  
     setupBooks();  
   }  
   private void setupBooks() {  
     records.remove(BOOKS);  
     records.add(BOOKS,  
         addBook(zenIsbn, "Zen And The Art Of Motorcycle Maintenance", true, zenUuid, new BigDecimal("9.95")),  
         addBook(godelEsherBach, "Godel, Escher, Bach: An Eternal Golden Braid", false, randomUUID(), new BigDecimal("20.00")),  
         addBook(cleanCode, "Clean Code: A Handbook of Agile Software Craftsmanship", true, randomUUID(), new BigDecimal("34.99")));  
   }  
   private Record addBook(URI bookisbn, String booktitle, boolean bookinPrint, UUID bookuuid, BigDecimal bookrrp) {  
     return Grammar.record(BOOKS.isbn, bookisbn, BOOKS.title, booktitle, BOOKS.inPrint, bookinPrint, BOOKS.uuid, bookuuid, BOOKS.rrp, bookrrp);  
   }  
 }  

Step 5: Retrieving the Book Entries via the Rerods
Following tests shows how to retrieve Book entities based on a certain criteria.

 @Test  
 public class BooksRecordTest {  

   . . .  

   @Test  
   public void itReturnsAllTheBooks() throws Exception {  

     //when  
     Sequence<Record> allBooks = records.get(BOOKS).filter(all());  

     //then  
     assertThat(allBooks.size(), is(3));  
   }  

   @Test  
   public void itReturnsAllThePaginatedBooksSortedByTitleInAscendingOrder() throws Exception {  

     //given  
     int currentPage = 1;  
     int numberOfRecordsPerPage = 2;  

     //when  
     Sequence<URI> allBooks = records.get(BOOKS).filter(all()).sortBy(ascending(title)).drop(currentPage - 1).take(numberOfRecordsPerPage).map(isbn);  

     //then  
     assertThat(allBooks, hasExactly(cleanCode, godelEsherBach));  
   }  

   @Test  
   public void itReturnsTheCleanCodeBookWhenSearchedByItsISBN() {  

     //when  
     Record theCleanCodeBook = records.get(BOOKS).filter(where(isbn, Grammar.is(cleanCode))).head();  

     //then  
     assertThat(theCleanCodeBook.get(isbn), Is.is(equalTo(cleanCode)));  
     assertThat(theCleanCodeBook.get(title), Is.is("Clean Code: A Handbook of Agile Software Craftsmanship"));  
     assertThat(theCleanCodeBook.get(inPrint), Is.is(true));  
     assertThat(theCleanCodeBook.get(rrp).setScale(DECIMALS_TO_TWO), Is.is(equalTo(new BigDecimal("34.99").setScale(DECIMALS_TO_TWO))));  
   }  

   @Test  
   public void itReturnsTheBookWithZenISBNWhenSearchedByTitleAndInPrintColumns() {  

     //when  
     Record theZenBook = records.get(BOOKS).filter(where(title, Grammar.contains("Zen"))).head();  

     //then  
     assertThat(theZenBook.get(isbn), Is.is(equalTo(zenIsbn)));  
     assertThat(theZenBook.get(title), Is.is("Zen And The Art Of Motorcycle Maintenance"));  
     assertThat(theZenBook.get(inPrint), Is.is(true));  
     assertThat(theZenBook.get(rrp).setScale(DECIMALS_TO_TWO), Is.is(equalTo(new BigDecimal("9.95").setScale(DECIMALS_TO_TWO))));  
   }  
 }  

Step 6: Updating a Book Entry via the Records
Following tests shows how to update a Book entity based on a certain criteria.

 @Test  
 public class BooksRecordTest {  

   . . .  

   @Test  
   public void itUpdatesTheBookTitleWhenGivenISBN() {  

     //given  
     String newZenTitle = "Zen And The Art Of Motorcycle Maintenance - II";  

     //when  
     records.put(BOOKS, update(using(isbn), record(isbn, zenIsbn, title, newZenTitle)));  

     //then  
     Record theZenBook = records.get(BOOKS).filter(where(title, Grammar.is(newZenTitle))).head();  
     assertThat(theZenBook.get(isbn), Is.is(equalTo(zenIsbn)));  
     assertThat(theZenBook.get(title), Is.is(newZenTitle));  
     assertThat(theZenBook.get(inPrint), Is.is(true));  
     assertThat(theZenBook.get(rrp).setScale(DECIMALS_TO_TWO), Is.is(equalTo(new BigDecimal("9.95").setScale(DECIMALS_TO_TWO))));  
   }  

   . . .  
}  


Step 7: Deleting a Book Entry via the Records
Following tests shows how to delete a Book entity based on a certain criteria.

 @Test  
 public class BooksRecordTest {  

   . . .  

   @Test  
   public void itDeletesTheBookWhenGivenItsISBN() {  

     //given  
     URI isbnToDelete = zenIsbn;  

     //when  
     records.remove(BOOKS, where(isbn, Grammar.is(isbnToDelete)));  

     //then  
     assertThat(records.get(BOOKS).filter(all()).size(), is(2));  
     assertThat(records.get(BOOKS).filter(where(isbn, Grammar.is(isbnToDelete))).isEmpty(), CoreMatchers.is(true));  
   }  

   . . .  
  }  

Summary:
This was a brief article on how to make use of Lazyrecords as a data source access framework in your development environment.

Sample code can be found here.

Monday, December 16, 2013

Yadic - Dependency Injection Framework from Google Code


Overview:
This article looks at Yadic, yet another Google Code framework for dependency injection. Yadic is a lightweight framework that promotes keeping implementation simple and yields lightning fast performance.

Here, we will look at a simple example how you could leverage the Yadic as your DI framework. Since the framework is so simple, most of the content in this article are self-explanatory.

You can learn more about the framework here.

A comprehensive sample code for this article can be found here.

Project Structure:

 ├── pom.xml  
 └── src  
   ├── main  
   │   └── java  
   │     └── org  
   │       └── fazlan  
   │         └── yadic  
   │           ├── common  
   │           │   ├── AbstractValueObject.java  
   │           │   └── ValueObject.java  
   │           ├── ds  
   │           │   ├── DataSourceConfig.java  
   │           │   ├── DataSourceDialect.java  
   │           │   ├── DataSourcePassword.java  
   │           │   ├── DataSourceUri.java  
   │           │   └── DataSourceUserName.java  
   │           └── persistence  
   │             ├── H2Connection.java  
   │             ├── JdbcConnectionActivator.java  
   │             ├── JdbcConnectionFactory.java  
   │             └── SqlDialect.java  
   └── test  
     └── java  
       └── org  
         └── fazlan  
           └── yadic  
             ├── ds  
             │   └── DataSourceConfigTest.java  
             ├── persistence  
             │   ├── JdbcConnectionActivatorTest.java  
             │   └── JdbcConnectionFactoryTest.java  
             └── util  
               └── DataSourceObjectMother.java  

Step 1: Creating the Project

 mvn archetype:generate -DartifactId=org.fazlan.yadic -DgroupId=org.fazlan.yadic -Dversion=1.0-SNAPSHOT -DinteractiveMode=false  

Step 2: Updating the Maven dependencies
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
   <modelVersion>4.0.0</modelVersion>  
   <groupId>org.fazlan.yadic</groupId>  
   <artifactId>yadic</artifactId>  
   <version>1.0-SNAPSHOT</version>  
   <packaging>jar</packaging>  
   <name>yadic</name>  
   <url>http://maven.apache.org</url>  
   <properties>  
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
     <testng.version>6.8</testng.version>  
     <yadic.version>168</yadic.version>  
     <hamcrest.version>1.3.RC2</hamcrest.version>  
     <totallylazy.version>1165</totallylazy.version>  
   </properties>  
   <dependencies>  
     <dependency>  
       <groupId>com.h2database</groupId>  
       <artifactId>h2</artifactId>  
       <version>1.3.170</version>  
     </dependency>  
     <dependency>  
       <groupId>com.googlecode.totallylazy</groupId>  
       <artifactId>totallylazy</artifactId>  
       <version>${totallylazy.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>com.googlecode.yadic</groupId>  
       <artifactId>yadic</artifactId>  
       <version>${yadic.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.hamcrest</groupId>  
       <artifactId>hamcrest-core</artifactId>  
       <version>${hamcrest.version}</version>  
       <scope>test</scope>  
     </dependency>  
     <dependency>  
       <groupId>org.hamcrest</groupId>  
       <artifactId>hamcrest-library</artifactId>  
       <version>${hamcrest.version}</version>  
       <scope>test</scope>  
     </dependency>  
     <dependency>  
       <groupId>org.testng</groupId>  
       <artifactId>testng</artifactId>  
       <version>${testng.version}</version>  
       <scope>test</scope>  
     </dependency>  
   </dependencies>  
 </project>  

Step 3: Creating the Container

 package org.fazlan.yadic.util;  

 import com.googlecode.yadic.Container;  
 import com.googlecode.yadic.SimpleContainer;  
 import org.fazlan.yadic.ds.DataSourceConfig;  

 public class DataSourceObjectMother {  
   . . .  

   public static Container newDIContainer() {  
     return new SimpleContainer();  
   }  
   . . .
 }  

Step 4: Adding Objects to the Container
The Framework allows several ways to add your objects into the container. Following are few ways in which you could use Yadic to manage the POJOs.

Adding as an Explicit Instance to the Container

 package org.fazlan.yadic.ds;  

 import java.util.Properties;  

 public class DataSourceConfig extends Properties {  

   public DataSourceConfig add(String key, Object value) {  
     put(key, value);  
     return this;  
   }  

   public DataSourceUri getUri() {  
     return new DataSourceUri(getProperty("datasource.uri"));  
   }  

   public DataSourcePassword getPassword() {  
     return new DataSourcePassword(getProperty("datasource.password"));  
   }  

   public DataSourceUserName getUserName() {  
     return new DataSourceUserName(getProperty("datasource.username"));  
   }  

   public DataSourceDialect getDialect() {  
     return new DataSourceDialect(getProperty("datasource.dialect"));  
   }  
 }  

Following is the corresponding Unit test

 package org.fazlan.yadic.ds;  

 import com.googlecode.yadic.Container;  
 import org.testng.annotations.Test;  
 import java.sql.SQLException;  
 import static org.fazlan.yadic.common.AbstractValueObject.valueOf;  
 import static org.fazlan.yadic.util.DataSourceObjectMother.getJdbcConfigForH2;  
 import static org.fazlan.yadic.util.DataSourceObjectMother.newDIContainer;  
 import static org.hamcrest.MatcherAssert.assertThat;  
 import static org.hamcrest.core.Is.is;  

 @Test  
 public class DataSourceConfigTest {  

   public void itInjectsInstanceAndWiresAllDependencies() throws SQLException {  

     //given  
     DataSourceConfig h2Config = getJdbcConfigForH2();  
     Container container = newDIContainer().addInstance(DataSourceConfig.class, h2Config);  

     //when  
     DataSourceConfig config = container.get(DataSourceConfig.class);  

     //then  
     assertThat(valueOf(config.getDialect()), is(valueOf(h2Config.getDialect())));  
     assertThat(valueOf(config.getUri()), is(valueOf(h2Config.getUri())));  
     assertThat(valueOf(config.getUserName()), is(valueOf(h2Config.getUserName())));  
     assertThat(valueOf(config.getPassword()), is(valueOf(h2Config.getPassword())));  
   }  
 }  

The above code keeps a reference to the instance h2Config via DataSourceConfig.class. Whenever, a dependency is required of type DataSourceConfig.class, then the object referenced by h2Config will be injected. Read here

Adding an Instance to the Container via an Activator
Activator is an implementation of a Callable. Inside a call method we define how our object should be created. Following is an example, how an activator could be used to instantiate a database connection. Read here


 package org.fazlan.yadic.persistence; 
 
 import java.io.Closeable;  
 import java.io.IOException;  
 import java.sql.Connection;  
 import java.util.concurrent.Callable;  
 import static com.googlecode.totallylazy.Closeables.safeClose;  

 public class JdbcConnectionActivator implements Callable<Connection>, Closeable {  

   private final JdbcConnectionFactory factory;  
   private Connection connection;  

   public JdbcConnectionActivator(JdbcConnectionFactory factory) {  
     this.factory = factory;  
   }  

   @Override  
   public Connection call() throws Exception {  
     connection = factory.getConnection();  
     return connection;  
   }  

   @Override  
   public void close() throws IOException {  
     safeClose(connection);  
   }  
 }  

Following is the corresponding Unit test.


 package org.fazlan.yadic.persistence;  

 import com.googlecode.yadic.Container;  
 import org.fazlan.yadic.ds.DataSourceConfig;  
 import org.testng.annotations.Test;  
 import java.sql.Connection;  
 import java.sql.SQLException;  
 import static com.googlecode.totallylazy.Closeables.safeClose;  
 import static org.fazlan.yadic.common.AbstractValueObject.valueOf;  
 import static org.fazlan.yadic.util.DataSourceObjectMother.getJdbcConfigForH2;  
 import static org.fazlan.yadic.util.DataSourceObjectMother.newDIContainer;  
 import static org.hamcrest.MatcherAssert.assertThat;  
 import static org.hamcrest.Matchers.equalToIgnoringCase;  
 import static org.hamcrest.core.Is.is;  
 import static org.hamcrest.core.IsNull.notNullValue;  

 @Test  
 public class JdbcConnectionActivatorTest {  

   public void itInjectsActivatorAndWiresAllDependencies() throws SQLException {  

     //given  
     DataSourceConfig config = getJdbcConfigForH2();  
     Container container = newDIContainer()  
         .addInstance(DataSourceConfig.class, config)  
         .add(JdbcConnectionFactory.class)  
         .addActivator(Connection.class, JdbcConnectionActivator.class); 
 
     //when  
     Connection connection = container.get(Connection.class);  

     //then  
     assertThat(connection, is(notNullValue()));  
     assertThat(connection.getMetaData().getURL(), is(valueOf(config.getUri())));  
     assertThat(connection.getMetaData().getUserName(), equalToIgnoringCase(valueOf(config.getUserName())));  

     //finally  
     safeClose(connection);  
   }  
 }  

The above adds the following to the contaniner,
- DataSourceConfig, database config related to H2 db.

- JdbcConnectionFactory, factory that creates the connection

- JdbcConnectionActivator, Activator that adds the created connection via a java.sql.Connection reference

and the container will return the connection instance created by the Activator via the java.sql.Connection.class

Step 5: Retrieving References from the Container
Retrieving the instance from the container is straight forward. You can use the get method on the container to fetch references. Read here.

Step 6: Dependency Resolution Mechanism and Auto-wiring in Yadic
How does Yadic manage the dependency resolution and auto-wiring of instance? Read here.

Summary:
This was a brief article on how to make use of Yadic as a DI framework in your development environment.

Sample code can be found here.

Saturday, July 13, 2013

Mockito Tutorial: TDD Framework for Mocking Functionality and Verifying User Stories

Overview:
This article looks at Mockito, a popular mocking framework for testing your Java code. Mockito API promotes writing clean and readable tests.

Here, we will look at a simple example how you could leverage the Mockito API to mock functionality in your tests.

Sample code can be found here.

Project Structure:
 org.fazlan.mockito.sample  
 ├── pom.xml  
 └── src  
   ├── main  
   │   └── java  
   │       └── org  
   │           └── fazlan  
   │               ├── CreditChecker.java  
   │               ├── CreditCheckException.java  
   │               └── Order.java  
   └── test  
     └── java  
       └── org  
         └── fazlan  
           └── OrderTest.java  

Step 1: Creating the Project

 mvn archetype:generate -DartifactId=org.fazlan.mockito.sample -DgroupId=org.fazlan -Dversion=1.0-SNAPSHOT -DinteractiveMode=false  

Step 2: Updating the Maven dependencies

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  <modelVersion>4.0.0</modelVersion>  
  <groupId>org.fazlan</groupId>  
  <artifactId>org.fazlan.mockito.sample</artifactId>  
  <version>1.0-SNAPSHOT</version>  
  <packaging>jar</packaging>  
  <name>mockito-sample</name>  
  <url>http://maven.apache.org</url>  
  <properties>  
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  </properties>  
  <dependencies>  
    <dependency>  
      <groupId>org.testng</groupId>  
      <artifactId>testng</artifactId>  
      <version>6.8.5</version>  
      <scope>test</scope>  
    </dependency>  
    <dependency>  
      <groupId>org.mockito</groupId>  
      <artifactId>mockito-core</artifactId>  
      <version>1.9.5</version>  
    </dependency>  
  </dependencies>  
 </project>  

Step 3: Defining the User story for placing an order

The following is a simple user story for placing an order, the story is based on an ordering system.

The story assumes that the system has clients and they have credit accounts associated with them. To successfully place an order, the clients should have sufficient funds, otherwise, the processing would fail. Thus, a credit check is performed before placing the order.

 Narrative:  
 In order to purchase goods for my needs  
 As a credit worthy client  
 I want to place an order

Step 4: Writing the test to verify the story

The following is a simple test for verifying the story. It's decorated using Mockito annotations, and they keep the code clean and easy to read.

 package org.fazlan; 
 
 import org.mockito.InjectMocks;  
 import org.testng.annotations.BeforeMethod;  
 import org.testng.annotations.Test;  
 import java.util.UUID; 
 
 import static junit.framework.Assert.assertEquals;  
 import static junit.framework.Assert.assertNotNull;  
 import static org.fazlan.Order.createOrderFor;
  
 import static org.mockito.Mockito.*;  
 import static org.mockito.MockitoAnnotations.Mock;  
 import static org.mockito.MockitoAnnotations.initMocks;  

 public class OrderTest {  

   private String clientNumber;  
   //injected by mockito  
   @Mock  
   private CreditChecker creditChecker;
  
   @InjectMocks  
   private Order order;  

   @BeforeMethod  
   public void setUp() {  
     //given  
     generateClientNumber();  
     order = createOrderFor(getClientNumber());  
     //initialises the mocks and injects them to the designated targets
     initMocks(this);
   }  

   @Test  
   public void shouldCreateOrderGivenClientNumber() {  
     //then  
     assertNotNull(order);  
     assertEquals(clientNumber, order.getClientNumber());  
   }  

   @Test(expectedExceptions = {CreditCheckException.class})  
   public void shouldNotPlaceTheOrderGivenClientCreditCheckFails() {  
     //given  
     theCreditCheckWouldThrowExceptionWhenCalled();  
     //when  
     order.place();  
   }  

   @Test  
   public void shouldPlaceTheOrderGivenClientCreditCheckPasses() {  
     //given  
     theCreditCheckWouldPassWhenCalled();  
     //when  
     order.place();  
     //then  
     assertNotNull(order.getOrderNumber());  
     verify(creditChecker).check(getClientNumber());  
   }  

   private void theCreditCheckWouldThrowExceptionWhenCalled() {  
     doThrow(new CreditCheckException()).when(creditChecker).check(getClientNumber());  
   }  

   private void theCreditCheckWouldPassWhenCalled() {  
     doNothing().when(creditChecker).check(getClientNumber());  
   }  

   private void generateClientNumber() {  
     clientNumber = UUID.randomUUID().toString();  
   }  

   private String getClientNumber() {  
     return clientNumber;  
   }  
 }  

IMPORTANT NOTE
Here, the CreditChecker is just an Interface, and there is no implementation. It could be either the implementation is not available at this point of time or, it's been developed by someone else, which we really don't care.

 package org.fazlan;  

 public interface CreditChecker {  
   void check(String clientNumber);  
 }  

However, what we are interested is in how the order placement functionality would react based on the outcome of the credit check. Thus, we can use Mockito to mock the credit check and make it behave the way we intend in order to test our logic while placing an order.

This is the beauty of a mocking framework, without having to implement the actual details you can still work on your tests. This is specially true in a TDD environment, where you want to  test a piece of code in isolation without having to care about it's infrastructure code or dependencies.

Step 5: Using Mockito to mock and verify the story

The tests are self-explanatory, and now lets take a close look the code.

   @Mock   
   private CreditChecker creditChecker;  

   @InjectMocks   
   private Order order;   

   @BeforeMethod   
   public void setUp() {   

    //given   
    generateClientNumber();   

    order = createOrderFor(getClientNumber());   

    //initialises the mocks and injects them to the designated targets  
    initMocks(this);  
   }   

The above code basically says, that the test should perform the following, and for each test (since it's been annotated with @BeforeMethod in testng framework), it should create an instance of an Order and initialise it with the mocked CreditChecker.
  • @Mock - Mock the interface CreditChecker. During the runtime, Mockito will generate a proxy that acts as an actual implementation of the interface and make it behave as we have specified.
  • @InjectMocks - Inject the mocked dependencies used in this instance. (e.i: creditChecker).
  • initMocks(this) - Initialise the above annotations for mocks and the target instance to be injected with in this test instance.
Lets assume, our business logic is such that if the client has insufficient funds, then the credit check should fail by throwing an CreditCheckException, otherwise, it'll do nothing.

Based on the above business logic, we advise the Mockito framework to behave exactly as per our expectation when we perform the credit check logic for different scenarios.

Scenario: When the credit check fails:

Here, we advise the Mockito framework to throw a CreditCheckException exception when the check() operation is called on the mocked creditCheck instance, so that we can test our order placement logic when credit check fails.

   @Test(expectedExceptions = {CreditCheckException.class})  
   public void shouldNotPlaceTheOrderGivenClientCreditCheckFails() {  
     //given  
     theCreditCheckWouldThrowExceptionWhenCalled();  
     //when  
     order.place();  
   }  
  
   private void theCreditCheckWouldThrowExceptionWhenCalled() {  
     doThrow(new CreditCheckException()).when(creditChecker).check(getClientNumber());  
   }  
 

Scenario: When the credit check passes:

Similarly, here we advise the Mockito framework to do nothing when the check() operation is called on the mocked creditCheck instance.

   @Test  
   public void shouldPlaceTheOrderGivenClientCreditCheckPasses() {  
     //given  
     theCreditCheckWouldPassWhenCalled();  
     //when  
     order.place();  
     //then  
     assertNotNull(order.getOrderNumber());  
     verify(creditChecker).check(getClientNumber());  
   } 

   private void theCreditCheckWouldPassWhenCalled() {  
     doNothing().when(creditChecker).check(getClientNumber());  
   }  

You can find more about the Mockito API documentation here.

Step 6: Based on the above tests, we can develop our Order.java as follows,

Following is a simple implementation of the Order.java, that has a method called 'place' to place the order against a given client.

 package org.fazlan;  
 
 import java.util.UUID;  

 //domain driven entity - @see DDD - Domain Driven Design for more.  
 public class Order {  

   private String orderNumber;  
   private String clientNumber;  
   private CreditChecker creditChecker;  

   private Order(String clientNumber) {  
     this.clientNumber = clientNumber;  
   }  

   public void place() {  
     doCreditCheck();  

     assignOrderNumber();  

     //do some processing and save the order  
   }  

   private void doCreditCheck() {  
     creditChecker.check(getClientNumber());  
   }  

   private void assignOrderNumber() {  
     orderNumber = UUID.randomUUID().toString();  
   }  

   public static Order createOrderFor(String clientNumber) {  
     return new Order(clientNumber);  
   }  

   public String getClientNumber() {  
     return clientNumber;  
   }  

   public String getOrderNumber() {  
     return orderNumber;  
   }  

   protected void setCreditChecker(CreditChecker creditChecker) {  
     this.creditChecker = creditChecker;  
   }  
 }  

Summary:
This was a brief article on how to make use of Mockito as a framework for mocking functionality in your tests in a TDD environment.

Sample code can be found here.

Sunday, June 2, 2013

jBehave Tutorial: BDD Framework for Verifying User Stories

Overview:
This article looks at jBehave, a popular BDD framework for Java.

There are many ways in which you could configure jBehave. Here, we look at the minimal set of configuration required to get the framework integrated with your BDD environment.

Sample code can be found here.

Project Structure:

org.fazlan.jbehave.exmaple
├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── org
    │           └── fazlan
    │               └── jbehave
    │                   └── exmaple
    │                       └── Calculator.java
    └── test
        ├── java
        │   └── org
        │       └── fazlan
        │           └── jbehave
        │               └── exmaple
        │                   ├── steps
        │                   │   └── AddTwoNumbersSteps.java
        │                   └── stories
        │                       └── CalculatorStories.java
        └── resources
            └── org
                └── fazlan
                    └── jbehave
                        └── exmaple
                            └── stories
                                └── calculator_stories.story

Step 1: Creating the Project

 mvn archetype:generate -DartifactId=org.fazlan.jbehave.exmaple -DgroupId=org.fazlan -Dversion=1.0-SNAPSHOT -DinteractiveMode=false  

Step 2: Updating the Maven dependencies
Update (2013-10-7) : Updated to include maven-jbehave-plugin.

NOTE: This assumes that you run only acceptance tests at maven integration-test phase, any unit tests will be skipped as per the pom.xml configuration.

 <?xml version="1.0" encoding="UTF-8"?>  
 <project xmlns="http://maven.apache.org/POM/4.0.0"  
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
   <modelVersion>4.0.0</modelVersion>  
   <groupId>org.fazlan</groupId>  
   <artifactId>org.fazlan.jbehave.exmaple</artifactId>  
   <version>1.0-SNAPSHOT</version>  
   <properties>  
     <jbehave.version>3.8</jbehave.version>  
     <junit.version>4.11</junit.version>  
     <failsafe.and.surefire.version>2.16</failsafe.and.surefire.version>  
   </properties>  
   <dependencies>  
     <dependency>  
       <groupId>junit</groupId>  
       <artifactId>junit</artifactId>  
       <version>${junit.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.jbehave</groupId>  
       <artifactId>jbehave-core</artifactId>  
       <version>${jbehave.version}</version>  
     </dependency>  
   </dependencies>  
   <build>  
     <plugins>  
       <plugin>  
         <groupId>org.apache.maven.plugins</groupId>  
         <artifactId>maven-surefire-plugin</artifactId>  
         <version>${failsafe.and.surefire.version}</version>  
         <configuration>  
           <!-- Disable unit tests -->  
           <skip>true</skip>  
         </configuration>  
       </plugin>  
       <plugin>  
         <groupId>org.apache.maven.plugins</groupId>  
         <artifactId>maven-failsafe-plugin</artifactId>  
         <version>${failsafe.and.surefire.version}</version>  
         <executions>  
           <execution>  
             <id>integration-test</id>  
             <goals>  
               <goal>integration-test</goal>  
               <goal>verify</goal>  
             </goals>  
           </execution>  
         </executions>  
         <configuration>  
           <includes>  
             <include>**/*Stories.java</include>  
           </includes>  
         </configuration>  
       </plugin>  
       <plugin>  
         <groupId>org.jbehave</groupId>  
         <artifactId>jbehave-maven-plugin</artifactId>  
         <version>${jbehave.version}</version>  
         <executions>  
           <execution>  
             <id>run-stories-as-embeddables</id>  
             <phase>integration-test</phase>  
             <configuration>  
               <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>  
               <includes>  
                 <include>**/*Stories.java</include>  
               </includes>  
               <ignoreFailureInStories>false</ignoreFailureInStories>  
               <ignoreFailureInView>false</ignoreFailureInView>  
             </configuration>  
             <goals>  
               <goal>run-stories-as-embeddables</goal>  
             </goals>  
           </execution>  
         </executions>  
       </plugin>  
     </plugins>  
   </build>  
 </project>  

Step 3: Defining the User story

A User story describes the behaviour of a piece of software and the expected outcome (acceptance criteria) for a given set of preconditions.

The following contains a simple user story for adding two numbers, which is defined in org/fazlan/jbehave/exmaple/stories/calculator_stories.story

 Narrative:  
 In order to quickly find out the sum of two numbers  
 As a user  
 I want to use a calculator to add two numbers
  
 Scenario: Add two valid numbers
  
 Given a calculator  
 When I add <number1> and <number2>  
 Then the outcome should <result>
  
 Examples:  
 |number1|number2|result|  
 |10|10|20|  

Step 4: Writing the test to verify the story

The following is the JUnit test for verifying and testing our add two numbers story.

 package org.fazlan.jbehave.exmaple.stories; 
 
 import org.fazlan.jbehave.exmaple.steps.AddTwoNumbersSteps; 
 
 import org.jbehave.core.configuration.Configuration;  
 import org.jbehave.core.junit.JUnitStory;  
 import org.jbehave.core.reporters.StoryReporterBuilder;  
 import org.jbehave.core.steps.InjectableStepsFactory;  
 import org.jbehave.core.steps.InstanceStepsFactory;  

 import static org.jbehave.core.reporters.Format.CONSOLE;  
 import static org.jbehave.core.reporters.Format.TXT;
  
 public class CalculatorStories extends JUnitStory {
  
   @Override  
   public Configuration configuration() {  
     return super.configuration()  
         .useStoryReporterBuilder(  
             new StoryReporterBuilder()  
                 .withDefaultFormats()  
                 .withFormats(CONSOLE, TXT));  
   }  

   // Here we specify the steps classes  
   @Override  
   public InjectableStepsFactory stepsFactory() {  
     return new InstanceStepsFactory(configuration(), new AddTwoNumbersSteps());  
   }  
 }  


IMPORTANT NOTE: By default, jBehave framework will look for *.story files defined in the same package as the corresponding *Stories.java file.

e.i: org.fazlan.jbehave.exmaple.stories.CalculatorStories.java will look for a *.story file called org/fazlan/jbehave/exmaple/stories/calculator_stories.story

Assume, you have defined your story in a file called 'CalculatorStory.story' then you can change the default behaviour of discovering stories by overriding the List<String> storyPaths() method in the following way,

 package org.fazlan.jbehave.exmaple.stories;  

 import org.fazlan.jbehave.exmaple.steps.AddTwoNumbersSteps;  

 import org.jbehave.core.configuration.Configuration;  
 import org.jbehave.core.junit.JUnitStory;  
 import org.jbehave.core.reporters.StoryReporterBuilder;  
 import org.jbehave.core.steps.InjectableStepsFactory;  
 import org.jbehave.core.steps.InstanceStepsFactory;  

 import static org.jbehave.core.reporters.Format.CONSOLE;  
 import static org.jbehave.core.reporters.Format.TXT;  

 public class CalculatorStories extends JUnitStory {  

   @Override  
   public Configuration configuration() {  
     return super.configuration()  
         .useStoryReporterBuilder(  
             new StoryReporterBuilder()  
                 .withDefaultFormats()  
                 .withFormats(CONSOLE, TXT));  
   }  

   // Here we specify the steps classes  
   @Override  
   public InjectableStepsFactory stepsFactory() {  
     return new InstanceStepsFactory(configuration(), new AddTwoNumbersSteps());  
   }  

   @Override  
   protected List<String> storyPaths() {  
     return new StoryFinder().findPaths(org.jbehave.core.io.CodeLocations.codeLocationFromPath("src/test/resources"), "**/CalculatorStory.story", "");  
   }  
 }  

Step 5: Writing the jBehave Step that verifies your story
There are multiple ways to write jBehave Steps, but in this article we focus on keeping this simple and write our Steps as POJOs.

 package org.fazlan.jbehave.exmaple.steps;  

 import org.fazlan.jbehave.exmaple.Calculator;  

 import org.jbehave.core.annotations.Given;  
 import org.jbehave.core.annotations.Named;  
 import org.jbehave.core.annotations.Then;  
 import org.jbehave.core.annotations.When;  

 public class AddTwoNumbersSteps {  

   private Calculator calculator;  

   @Given("a calculator")  
   public void givenACalculator() {  
     calculator = new Calculator();  
   }  

   @When("I add <number1> and <number2>")  
   public void whenIAddNumber1AndNumber2(@Named("number1")int number1, @Named("number2")int number2) {  
     calculator.add(number1, number2);  
   }  

   @Then("the outcome should <result>")  
   public void thenTheOutcomeShould(@Named("result")int result) {  
     assert calculator.getResult() == result;  
   }  
 }  

Step 6: Implementing the Calculator.java to meet our User story acceptance criteria
Following is a simple implementation of a Calculator that has a method called 'add' to add two numbers.

 package org.fazlan.jbehave.exmaple;
  
 public class Calculator {  

   private int result;  

   public void add(int number1, int number2) {  
     result = number1 + number2;  
   }  

   public int getResult() {  
     return result;  
   }  
 }  


Step 7: Running your tests
You can run the acceptance tests issuing the following Maven command.

mvn clean integration-test

Summary:
This was a brief article on how to integrate jBehave with Maven for BDD with your application.

Sample code can be found here.