Work on #404, updated class diagram and javadoc. Passed checkstyle checks

This commit is contained in:
Narendra Pathai 2016-03-23 13:13:19 +05:30
parent fa077c8be9
commit 3f7ead5ca5
12 changed files with 237 additions and 84 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -1,45 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.1.8" icons="true" always-add-relationships="false" generalizations="true" realizations="true" <class-diagram version="1.1.8" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
associations="true" dependencies="false" nesting-relationships="true"> associations="true" dependencies="false" nesting-relationships="true">
<class id="1" language="java" name="com.iluwatar.Customer" project="dao" <class id="1" language="java" name="com.iluwatar.dao.App" project="dao"
file="/dao/src/main/java/com/iluwatar/Customer.java" binary="false" corner="BOTTOM_RIGHT"> file="/dao/src/main/java/com/iluwatar/dao/App.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="176" y="337"/> <position height="-1" width="-1" x="910" y="191"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true"> sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/> <attributes public="true" package="true" protected="true" private="false" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/> <operations public="true" package="true" protected="true" private="false" static="true"/>
</display> </display>
</class> </class>
<class id="2" language="java" name="com.iluwatar.CustomerDaoImpl" project="dao" <interface id="2" language="java" name="com.iluwatar.dao.CustomerDao" project="dao"
file="/dao/src/main/java/com/iluwatar/CustomerDaoImpl.java" binary="false" corner="BOTTOM_RIGHT"> file="/dao/src/main/java/com/iluwatar/dao/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="540" y="334"/> <position height="-1" width="-1" x="536" y="187"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<interface id="3" language="java" name="com.iluwatar.CustomerDao" project="dao"
file="/dao/src/main/java/com/iluwatar/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="536" y="131"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true"> sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/> <attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/> <operations public="true" package="true" protected="true" private="true" static="true"/>
</display> </display>
</interface> </interface>
<realization id="4"> <class id="3" language="java" name="com.iluwatar.dao.InMemoryCustomerDao" project="dao"
<end type="SOURCE" refId="2"/> file="/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
<end type="TARGET" refId="3"/> <position height="-1" width="-1" x="289" y="455"/>
</realization> <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
<association id="5"> sort-features="false" accessors="true" visibility="true">
<end type="SOURCE" refId="2" navigable="false"> <attributes public="true" package="true" protected="true" private="false" static="true"/>
<attribute id="6" name="customers"/> <operations public="true" package="true" protected="true" private="true" static="true"/>
<multiplicity id="7" minimum="0" maximum="2147483647"/> </display>
</class>
<class id="4" language="java" name="com.iluwatar.dao.DBCustomerDao" project="dao"
file="/dao/src/main/java/com/iluwatar/dao/DBCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="751" y="456"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="false" static="true"/>
<operations public="true" package="true" protected="true" private="false" static="true"/>
</display>
</class>
<interface id="5" language="java" name="javax.sql.DataSource" project="dao"
file="/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="1083" y="459"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</interface>
<association id="6">
<end type="SOURCE" refId="4" navigable="false">
<attribute id="7" name="dataSource"/>
<multiplicity id="8" minimum="0" maximum="1"/>
</end> </end>
<end type="TARGET" refId="1" navigable="true"/> <end type="TARGET" refId="5" navigable="true"/>
<display labels="true" multiplicity="true"/> <display labels="true" multiplicity="true"/>
</association> </association>
<realization id="9">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="2"/>
</realization>
<dependency id="10">
<end type="SOURCE" refId="1"/>
<end type="TARGET" refId="2"/>
</dependency>
<realization id="11">
<end type="SOURCE" refId="4"/>
<end type="TARGET" refId="2"/>
</realization>
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" <classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true"> sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/> <attributes public="true" package="true" protected="true" private="true" static="true"/>

View File

@ -47,6 +47,7 @@
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>de.bechte.junit</groupId> <groupId>de.bechte.junit</groupId>

View File

@ -20,31 +20,39 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package com.iluwatar.dao; package com.iluwatar.dao;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Stream;
import javax.sql.DataSource;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.h2.jdbcx.JdbcDataSource;
/** /**
*
* Data Access Object (DAO) is an object that provides an abstract interface to some type of * Data Access Object (DAO) is an object that provides an abstract interface to some type of
* database or other persistence mechanism. By mapping application calls to the persistence layer, * database or other persistence mechanism. By mapping application calls to the persistence layer,
* DAO provide some specific data operations without exposing details of the database. This * DAO provide some specific data operations without exposing details of the database. This
* isolation supports the Single responsibility principle. It separates what data accesses the * isolation supports the Single responsibility principle. It separates what data accesses the
* application needs, in terms of domain-specific objects and data types (the public interface of * application needs, in terms of domain-specific objects and data types (the public interface of
* the DAO), from how these needs can be satisfied with a specific DBMS. * the DAO), from how these needs can be satisfied with a specific DBMS.
* <p> *
* With the DAO pattern, we can use various method calls to retrieve/add/delete/update data without * <p>With the DAO pattern, we can use various method calls to retrieve/add/delete/update data
* directly interacting with the data. The below example demonstrates basic CRUD operations: select, * without directly interacting with the data source. The below example demonstrates basic CRUD
* add, update, and delete. * operations: select, add, update, and delete.
*
* *
*/ */
public class App { public class App {
private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
private static Logger log = Logger.getLogger(App.class); private static Logger log = Logger.getLogger(App.class);
/** /**
* Program entry point. * Program entry point.
* *
@ -52,17 +60,54 @@ public class App {
* @throws Exception if any error occurs. * @throws Exception if any error occurs.
*/ */
public static void main(final String[] args) throws Exception { public static void main(final String[] args) throws Exception {
final CustomerDao customerDao = new InMemoryCustomerDao(); final CustomerDao inMemoryDao = new InMemoryCustomerDao();
performOperationsUsing(inMemoryDao);
final DataSource dataSource = createDataSource();
createSchema(dataSource);
final CustomerDao dbDao = new DbCustomerDao(dataSource);
performOperationsUsing(dbDao);
deleteSchema(dataSource);
}
private static void deleteSchema(DataSource dataSource) throws SQLException {
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute("DROP TABLE CUSTOMERS");
}
}
private static void createSchema(DataSource dataSource) throws SQLException {
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute("CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100), "
+ "LNAME VARCHAR(100))");
}
}
private static DataSource createDataSource() {
JdbcDataSource dataSource = new JdbcDataSource();
dataSource.setURL(DB_URL);
return dataSource;
}
private static void performOperationsUsing(final CustomerDao customerDao) throws Exception {
addCustomers(customerDao); addCustomers(customerDao);
log.info("customerDao.getAllCustomers(): " + customerDao.getAll()); log.info("customerDao.getAllCustomers(): ");
log.info("customerDao.getCusterById(2): " + customerDao.getById(2)); try (Stream<Customer> customerStream = customerDao.getAll()) {
customerStream.forEach((customer) -> log.info(customer));
}
log.info("customerDao.getCustomerById(2): " + customerDao.getById(2));
final Customer customer = new Customer(4, "Dan", "Danson"); final Customer customer = new Customer(4, "Dan", "Danson");
customerDao.add(customer); customerDao.add(customer);
log.info("customerDao.getAllCustomers(): " + customerDao.getAll()); log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
customer.setFirstName("Daniel"); customer.setFirstName("Daniel");
customer.setLastName("Danielson"); customer.setLastName("Danielson");
customerDao.update(customer); customerDao.update(customer);
log.info("customerDao.getAllCustomers(): " + customerDao.getAll()); log.info("customerDao.getAllCustomers(): ");
try (Stream<Customer> customerStream = customerDao.getAll()) {
customerStream.forEach((cust) -> log.info(cust));
}
customerDao.delete(customer); customerDao.delete(customer);
log.info("customerDao.getAllCustomers(): " + customerDao.getAll()); log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
} }

View File

@ -20,11 +20,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package com.iluwatar.dao; package com.iluwatar.dao;
/** /**
* * A customer POJO that represents the data that will be read from the data source.
* Customer
* *
*/ */
public class Customer { public class Customer {
@ -34,7 +34,7 @@ public class Customer {
private String lastName; private String lastName;
/** /**
* Constructor * Creates an instance of customer.
*/ */
public Customer(final int id, final String firstName, final String lastName) { public Customer(final int id, final String firstName, final String lastName) {
this.id = id; this.id = id;
@ -73,12 +73,12 @@ public class Customer {
} }
@Override @Override
public boolean equals(final Object o) { public boolean equals(final Object that) {
boolean isEqual = false; boolean isEqual = false;
if (this == o) { if (this == that) {
isEqual = true; isEqual = true;
} else if (o != null && getClass() == o.getClass()) { } else if (that != null && getClass() == that.getClass()) {
final Customer customer = (Customer) o; final Customer customer = (Customer) that;
if (getId() == customer.getId()) { if (getId() == customer.getId()) {
isEqual = true; isEqual = true;
} }

View File

@ -20,12 +20,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package com.iluwatar.dao; package com.iluwatar.dao;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
*
* In an application the Data Access Object (DAO) is a part of Data access layer. It is an object * In an application the Data Access Object (DAO) is a part of Data access layer. It is an object
* that provides an interface to some type of persistence mechanism. By mapping application calls * that provides an interface to some type of persistence mechanism. By mapping application calls
* to the persistence layer, DAO provides some specific data operations without exposing details * to the persistence layer, DAO provides some specific data operations without exposing details
@ -33,25 +33,25 @@ import java.util.stream.Stream;
* data accesses the application needs, in terms of domain-specific objects and data types * data accesses the application needs, in terms of domain-specific objects and data types
* (the public interface of the DAO), from how these needs can be satisfied with a specific DBMS, * (the public interface of the DAO), from how these needs can be satisfied with a specific DBMS,
* database schema, etc. * database schema, etc.
* <br/><br/> *
* Any change in the way data is stored and retrieved will not change the client code as the client * <p>Any change in the way data is stored and retrieved will not change the client code as the
* will be using interface and need not worry about exact source. * client will be using interface and need not worry about exact source.
* *
* @see InMemoryCustomerDao * @see InMemoryCustomerDao
* @see DBCustomerDao * @see DbCustomerDao
*/ */
public interface CustomerDao { public interface CustomerDao {
/** /**
* @return all the customers as a stream. The stream may be lazily or eagerly evaluated based on the * @return all the customers as a stream. The stream may be lazily or eagerly evaluated based
* implementation. The stream must be closed after use. * on the implementation. The stream must be closed after use.
* @throws Exception if any error occurs. * @throws Exception if any error occurs.
*/ */
Stream<Customer> getAll() throws Exception; Stream<Customer> getAll() throws Exception;
/** /**
* @param id unique identifier of the customer. * @param id unique identifier of the customer.
* @return customer with unique identifier <code>id</code> is found, null otherwise. * @return customer with unique identifier <code>id</code> if found, null otherwise.
* @throws Exception if any error occurs. * @throws Exception if any error occurs.
*/ */
Customer getById(int id) throws Exception; Customer getById(int id) throws Exception;

View File

@ -20,6 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package com.iluwatar.dao; package com.iluwatar.dao;
import java.sql.Connection; import java.sql.Connection;
@ -35,27 +36,39 @@ import java.util.stream.StreamSupport;
import javax.sql.DataSource; import javax.sql.DataSource;
/** /**
* * An implementation of {@link CustomerDao} that persists customers in RDBMS.
* *
*/ */
public class DBCustomerDao implements CustomerDao { public class DbCustomerDao implements CustomerDao {
private final DataSource dataSource; private final DataSource dataSource;
public DBCustomerDao(DataSource dataSource) { /**
* Creates an instance of {@link DbCustomerDao} which uses provided <code>dataSource</code>
* to store and retrieve customer information.
*
* @param dataSource a non-null dataSource.
*/
public DbCustomerDao(DataSource dataSource) {
this.dataSource = dataSource; this.dataSource = dataSource;
} }
/**
* @return a lazily populated stream of customers. Note the stream returned must be closed to
* free all the acquired resources. The stream keeps an open connection to the database till
* it is complete or is closed manually.
*/
@Override @Override
public Stream<Customer> getAll() throws Exception { public Stream<Customer> getAll() throws Exception {
Connection connection; Connection connection;
try { try {
connection = getConnection(); connection = getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS"); PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS");
ResultSet resultSet = statement.executeQuery(); ResultSet resultSet = statement.executeQuery();
return StreamSupport.stream(new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE, Spliterator.ORDERED) { return StreamSupport.stream(new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE,
Spliterator.ORDERED) {
@Override @Override
public boolean tryAdvance(Consumer<? super Customer> action) { public boolean tryAdvance(Consumer<? super Customer> action) {
try { try {
@ -65,15 +78,15 @@ public class DBCustomerDao implements CustomerDao {
action.accept(createCustomer(resultSet)); action.accept(createCustomer(resultSet));
return true; return true;
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); throw new RuntimeException(e);
return false;
} }
}}, false).onClose(() -> mutedClose(connection)); }
}, false).onClose(() -> mutedClose(connection));
} catch (SQLException e) { } catch (SQLException e) {
throw new Exception(e.getMessage(), e); throw new Exception(e.getMessage(), e);
} }
} }
private Connection getConnection() throws SQLException { private Connection getConnection() throws SQLException {
return dataSource.getConnection(); return dataSource.getConnection();
} }
@ -91,31 +104,40 @@ public class DBCustomerDao implements CustomerDao {
resultSet.getString("FNAME"), resultSet.getString("FNAME"),
resultSet.getString("LNAME")); resultSet.getString("LNAME"));
} }
/**
* {@inheritDoc}
*/
@Override @Override
public Customer getById(int id) throws Exception { public Customer getById(int id) throws Exception {
try (Connection connection = getConnection(); try (Connection connection = getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) { PreparedStatement statement =
statement.setInt(1, id); connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) {
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) { statement.setInt(1, id);
return createCustomer(resultSet); ResultSet resultSet = statement.executeQuery();
} else { if (resultSet.next()) {
return null; return createCustomer(resultSet);
} } else {
return null;
}
} catch (SQLException ex) { } catch (SQLException ex) {
throw new Exception(ex.getMessage(), ex); throw new Exception(ex.getMessage(), ex);
} }
} }
/**
* {@inheritDoc}
*/
@Override @Override
public boolean add(Customer customer) throws Exception { public boolean add(Customer customer) throws Exception {
if (getById(customer.getId()) != null) { if (getById(customer.getId()) != null) {
return false; return false;
} }
try (Connection connection = getConnection(); try (Connection connection = getConnection();
PreparedStatement statement = connection.prepareStatement("INSERT INTO CUSTOMERS VALUES (?,?,?)")) { PreparedStatement statement =
connection.prepareStatement("INSERT INTO CUSTOMERS VALUES (?,?,?)")) {
statement.setInt(1, customer.getId()); statement.setInt(1, customer.getId());
statement.setString(2, customer.getFirstName()); statement.setString(2, customer.getFirstName());
statement.setString(3, customer.getLastName()); statement.setString(3, customer.getLastName());
@ -126,10 +148,14 @@ public class DBCustomerDao implements CustomerDao {
} }
} }
/**
* {@inheritDoc}
*/
@Override @Override
public boolean update(Customer customer) throws Exception { public boolean update(Customer customer) throws Exception {
try (Connection connection = getConnection(); try (Connection connection = getConnection();
PreparedStatement statement = connection.prepareStatement("UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?")) { PreparedStatement statement =
connection.prepareStatement("UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?")) {
statement.setString(1, customer.getFirstName()); statement.setString(1, customer.getFirstName());
statement.setString(2, customer.getLastName()); statement.setString(2, customer.getLastName());
statement.setInt(3, customer.getId()); statement.setInt(3, customer.getId());
@ -139,10 +165,14 @@ public class DBCustomerDao implements CustomerDao {
} }
} }
/**
* {@inheritDoc}
*/
@Override @Override
public boolean delete(Customer customer) throws Exception { public boolean delete(Customer customer) throws Exception {
try (Connection connection = getConnection(); try (Connection connection = getConnection();
PreparedStatement statement = connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) { PreparedStatement statement =
connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) {
statement.setInt(1, customer.getId()); statement.setInt(1, customer.getId());
return statement.executeUpdate() > 0; return statement.executeUpdate() > 0;
} catch (SQLException ex) { } catch (SQLException ex) {

View File

@ -20,6 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package com.iluwatar.dao; package com.iluwatar.dao;
import java.util.HashMap; import java.util.HashMap;

View File

@ -20,6 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package com.iluwatar.dao; package com.iluwatar.dao;
import org.junit.Test; import org.junit.Test;

View File

@ -20,6 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package com.iluwatar.dao; package com.iluwatar.dao;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;

View File

@ -28,33 +28,51 @@ import org.mockito.Mockito;
import de.bechte.junit.runners.context.HierarchicalContextRunner; import de.bechte.junit.runners.context.HierarchicalContextRunner;
/**
* Tests {@link DbCustomerDao}.
*/
@RunWith(HierarchicalContextRunner.class) @RunWith(HierarchicalContextRunner.class)
public class DBCustomerDaoTest { public class DbCustomerDaoTest {
private static final String DB_URL = "jdbc:h2:~/dao:customerdb"; private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
private DBCustomerDao dao; private DbCustomerDao dao;
private Customer existingCustomer = new Customer(1, "Freddy", "Krueger"); private Customer existingCustomer = new Customer(1, "Freddy", "Krueger");
/**
* Creates customers schema.
* @throws SQLException if there is any error while creating schema.
*/
@Before @Before
public void createSchema() throws SQLException { public void createSchema() throws SQLException {
try (Connection connection = DriverManager.getConnection(DB_URL); try (Connection connection = DriverManager.getConnection(DB_URL);
Statement statement = connection.createStatement()) { Statement statement = connection.createStatement()) {
statement.execute("CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100), LNAME VARCHAR(100))"); statement.execute("CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100),"
+ " LNAME VARCHAR(100))");
} }
} }
/**
* Represents the scenario where DB connectivity is present.
*/
public class ConnectionSuccess { public class ConnectionSuccess {
/**
* Setup for connection success scenario.
* @throws Exception if any error occurs.
*/
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
JdbcDataSource dataSource = new JdbcDataSource(); JdbcDataSource dataSource = new JdbcDataSource();
dataSource.setURL(DB_URL); dataSource.setURL(DB_URL);
dao = new DBCustomerDao(dataSource); dao = new DbCustomerDao(dataSource);
boolean result = dao.add(existingCustomer); boolean result = dao.add(existingCustomer);
assertTrue(result); assertTrue(result);
} }
public class NonExistantCustomer { /**
* Represents the scenario when DAO operations are being performed on a non existing customer.
*/
public class NonExistingCustomer {
@Test @Test
public void addingShouldResultInSuccess() throws Exception { public void addingShouldResultInSuccess() throws Exception {
@ -97,6 +115,11 @@ public class DBCustomerDaoTest {
} }
} }
/**
* Represents a scenario where DAO operations are being performed on an already existing
* customer.
*
*/
public class ExistingCustomer { public class ExistingCustomer {
@Test @Test
@ -135,14 +158,23 @@ public class DBCustomerDaoTest {
} }
} }
public class DBConnectivityIssue { /**
* Represents a scenario where DB connectivity is not present due to network issue, or
* DB service unavailable.
*
*/
public class ConnectivityIssue {
private static final String EXCEPTION_CAUSE = "Connection not available"; private static final String EXCEPTION_CAUSE = "Connection not available";
@Rule public ExpectedException exception = ExpectedException.none(); @Rule public ExpectedException exception = ExpectedException.none();
/**
* setup a connection failure scenario.
* @throws SQLException if any error occurs.
*/
@Before @Before
public void setUp() throws SQLException { public void setUp() throws SQLException {
dao = new DBCustomerDao(mockedDatasource()); dao = new DbCustomerDao(mockedDatasource());
exception.expect(Exception.class); exception.expect(Exception.class);
exception.expectMessage(EXCEPTION_CAUSE); exception.expectMessage(EXCEPTION_CAUSE);
} }
@ -186,6 +218,10 @@ public class DBCustomerDaoTest {
} }
/**
* Delete customer schema for fresh setup per test.
* @throws SQLException if any error occurs.
*/
@After @After
public void deleteSchema() throws SQLException { public void deleteSchema() throws SQLException {
try (Connection connection = DriverManager.getConnection(DB_URL); try (Connection connection = DriverManager.getConnection(DB_URL);

View File

@ -20,6 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package com.iluwatar.dao; package com.iluwatar.dao;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -36,6 +37,9 @@ import org.junit.runner.RunWith;
import de.bechte.junit.runners.context.HierarchicalContextRunner; import de.bechte.junit.runners.context.HierarchicalContextRunner;
/**
* Tests {@link InMemoryCustomerDao}.
*/
@RunWith(HierarchicalContextRunner.class) @RunWith(HierarchicalContextRunner.class)
public class InMemoryCustomerDaoTest { public class InMemoryCustomerDaoTest {
@ -47,8 +51,12 @@ public class InMemoryCustomerDaoTest {
dao = new InMemoryCustomerDao(); dao = new InMemoryCustomerDao();
dao.add(CUSTOMER); dao.add(CUSTOMER);
} }
public class NonExistantCustomer { /**
* Represents the scenario when the DAO operations are being performed on a non existent
* customer.
*/
public class NonExistingCustomer {
@Test @Test
public void addingShouldResultInSuccess() throws Exception { public void addingShouldResultInSuccess() throws Exception {
@ -91,6 +99,10 @@ public class InMemoryCustomerDaoTest {
} }
} }
/**
* Represents the scenario when the DAO operations are being performed on an already existing
* customer.
*/
public class ExistingCustomer { public class ExistingCustomer {
@Test @Test