mercredi 29 avril 2015

DAO Design Pattern vs DBUnit Code

I am not sure if my DAO or DBUnit Test needs some refactoring. Can somebody please guide on the situation that I am facing?

I have a DAO that gets some data from the DB by getting a Connection object and then it closes all the resources(ResultSet, Statement and Connection).

I am testing this DAO using DBUnit framework where I am doing two DB operations in this DBUnit Test here: 1) Creating a table and then loading data from XML dataset file 2) Testing the actual getDataById(int id) method present in the DAO

The problem is that my second getDataById(id) method is not able to get a DB connnection object because my DAO already closed it while performing step 1 above.

The code snippet that actually releases all the resources is shown below.

DAO.java (Code snippet)

public void releaseResources(ResultSet rs, Statement stmt, Connection cn) {
        System.out.println("rs = " + rs);
        System.out.println("stmt = " + stmt);
        System.out.println("cn = " + cn);
        try {
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
            if (cn != null) {
                cn.close();
            }
        } catch (SQLException ex) {
            System.out.println("Exception while closing DB resources rs, stmt or cn......." + ex);
        }
    }

Hence in order to get my DBUnit tests to work I had to overload the above releaseResources() method so that it does not close the connection object which could be used in my getDataById(int id) unit test. Shown below.

**DAO.java (Code snippet with overloaded method) **

//OVERLOADED JUST TO GET DBUNIT TESTS WORKING !!! :(
public void releaseResources(Statement stmt) {
    System.out.println("\nReleasing db resources now.... 1111");
    System.out.println("stmt = " + stmt);
    try {
        if (stmt != null) {
            stmt.close();
        }
    } catch (SQLException ex) {
        System.out.println("Exception while closing DB resources stmt......." + ex);
    }
}

I am not sure if this is right design. Can somebody please guide on as how can I improve this?

Complete code is shown below for further reference.

StateDaoTest.java

public class StateDaoTest {

    protected static Connection connection;
    protected static HsqldbConnection dbunitConnection;
    protected static StateDao dao = new StateDao();

    @BeforeClass
    public static void setupDatabase() throws Exception {
        Class.forName("org.hsqldb.jdbcDriver");
        connection = DriverManager.getConnection("jdbc:hsqldb:mem:my-project-test;shutdown=true");
        dbunitConnection = new HsqldbConnection(connection, null);
    }

    @Before
    public void createTable() throws SQLException {
        dao.setConnection(connection);
        dao.createTables();
    }

    protected IDataSet getDataSet(String name) throws Exception {
        InputStream inputStream = getClass().getResourceAsStream(name);
        assertNotNull("file" + name + " not found in classpath", inputStream);
        Reader reader = new InputStreamReader(inputStream);
        FlatXmlDataSet dataset = new FlatXmlDataSet(reader);
        return dataset;
    }

    @AfterClass
    public static void closeDatabase() throws Exception {
        System.out.println("\ninto the closeDatabase() method...");
        System.out.println("connection = " + connection);
        System.out.println("dbunitConnection = " + dbunitConnection);
        if (connection != null) {
            connection.close();
            connection = null;
        }
        if (dbunitConnection != null) {
            dbunitConnection.close();
            dbunitConnection = null;
        }
    }

    @Test
    public void testGetStateById() throws Exception {
        IDataSet setupDataSet = getDataSet("/states.xml");
        DatabaseOperation.CLEAN_INSERT.execute(dbunitConnection, setupDataSet);
        State state = dao.getStateById(1);
        assertNotNull(state);
        assertEquals("Pennsylvania", state.getName());
        assertEquals("PA", state.getStateCode());
        assertNotNull(state.getTaxPct());
        assertEquals("Y", state.getActive());
    }

}

StateDao.java

public class StateDao {

    private Connection connection;

    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    //added for dbunit tests
    public void createTables() throws SQLException {
        String sql = "CREATE TABLE states (stateId INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1), "
                + "stateCd VARCHAR(10), name VARCHAR(20), taxPct NUMERIC, active CHAR(1))";
        Statement stmt = null;
        try {
            stmt = connection.createStatement();
            stmt.execute(sql);
        } finally {
            releaseResources(stmt);
        }
    }

    public State getStateById(long id) {
        String sql = "SELECT * FROM states WHERE stateId = " + id;

        Statement stmt = null;
        ResultSet rs = null;
        State state = null;

        System.out.println(sql);

        try {
            stmt = connection.createStatement();
            rs = stmt.executeQuery(sql);
            while (rs != null && rs.next()) {
                String stateId = StringUtils.defaultString(rs.getString("stateId"));
                String stateCd = StringUtils.defaultString(rs.getString("stateCd"));
                String name = StringUtils.defaultString(rs.getString("name"));
                String taxPct = StringUtils.defaultIfEmpty(rs.getString("taxPct"), "0");
                String active = StringUtils.defaultString(rs.getString("active"));
                state = new State(new Integer(stateId), stateCd, name, new BigDecimal(taxPct), active);
                System.out.println("state = " + state);
            }
            System.out.println("state = " + state);
        } catch (SQLException ex) {
            System.out.println("Exception whiile fetching data for a state......." + ex);
        } finally {
            releaseResources(rs, stmt, connection);
        }
        return state;
    }

    public void releaseResources(ResultSet rs, Statement stmt, Connection cn) {
        System.out.println("\nReleasing db resources now....2222");
        System.out.println("rs = " + rs);
        System.out.println("stmt = " + stmt);
        System.out.println("cn = " + cn);
        try {
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
            if (cn != null) {
                cn.close();
            }
        } catch (SQLException ex) {
            System.out.println("Exception while closing DB resources rs, stmt or cn......." + ex);
        }
    }

    //added for dbunit tests
    public void releaseResources(Statement stmt) {
        System.out.println("\nReleasing db resources now.... 1111");
        System.out.println("stmt = " + stmt);
        try {
            if (stmt != null) {
                stmt.close();
            }
        } catch (SQLException ex) {
            System.out.println("Exception while closing DB resources stmt......." + ex);
        }
    }  

}

Aucun commentaire:

Enregistrer un commentaire