5

I'm unable to mock the close() method on java.sql.Connection object. My ultimate goal is to do connection pooling while running JUnit tests. This will eliminate connection overhead during unit testing as the code under test executes connect/close for every SQL request.

I have code snippet which demonstrates the problem. It successfully mocks the connect(), but fails to mock the close() call. Both connect, and close must be mocked to managed pooled connections.

Since the close() method does not return a value, I'm using EasyMock.expectLastCall.

The following code defines the mock, but the print statement for close() is never executed and my connections are closed.

public class ConnectionPoolTest {

    public static final String DATASOURCE_REF = "jdbc/cloudexDS";
    public static final String ref = "osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=" + DATASOURCE_REF + ")";

    @BeforeClass
    public static void setUpBeforeClass() throws Exception 
    {
        //
        //  set up a simple database connection (e.g. DB2SimpleDataSource) 
        //
        DataSource dbds = connect("localhost", "dbname", "userid", "password", 50000);

        //
        //  now set up mock for the datasource to use the above connection
        //
        Context context = EasyMock.createNiceMock(Context.class);
        System.setProperty(Context.INITIAL_CONTEXT_FACTORY, CEXInitialContextFactory.class.getName());
        CEXInitialContextFactory.setCurrentContext(context);

        try {
            expect(context.lookup(ref)).andReturn(dbds).anyTimes();
            replay(context);
        } catch (NamingException e1) {
            e1.printStackTrace();
        }

        //
        //  mock the close()
        //
        Connection conn = EasyMock.createNiceMock(Connection.class);
        try {
            conn.close();
            expectLastCall().andAnswer(new IAnswer<Object>() {
                public Object answer() {
                    System.out.println("Close connection");
                    return null;
                }
            });
            replay(conn);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    @Test
    public void testMakeRequest() 
    {
        try {
            Connection conn = getConnection();
            ResultSet rset = conn.createStatement().executeQuery("SELECT COUNT(*) FROM SYSCAT.TABLES");
            if(rset.next()) {
                System.out.println("Count=" + rset.getString(1));
            }
            conn.close();
        } catch (Exception ex) {
            fail("Exception thrown, msg=" + ex.getMessage());
        }
    }

    /**
     * get a connection to the database
     * 
     * Note:  The ic.lookup is mocked and will return a database connection
     * 
     * @return  connection object
     * @throws NamingException
     * @throws SQLException
     */
    private Connection getConnection() throws NamingException, SQLException 
    {
        DataSource cloudexds = null;

        try {
            InitialContext ic = new InitialContext();
            cloudexds = (DataSource) ic.lookup(ref);
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return cloudexds.getConnection();
    }

    /**
     * setup a connection to the database.  This will be used with mock
     * 
     * @param hostname
     * @param dbname
     * @param schema
     * @param userid
     * @param password
     * @param port
     * @return
     */
    private static DataSource connect(String hostname, String dbname, String userid, String password, Integer port)
    {
        DB2SimpleDataSource dbds = new DB2SimpleDataSource();
        //
        //  local 'docker' database
        //
        dbds.setDatabaseName(dbname);
        dbds.setUser(userid);
        dbds.setPassword(password);
        dbds.setServerName(hostname);
        dbds.setPortNumber(port);
        dbds.setDriverType(4);

        try {
            dbds.getConnection();
        } catch (Exception ex) {
            fail("Cannot connect to the " + dbname + " database, msg=" + ex.getMessage());
        }
        return dbds;
    }
}

I'm using EasyMock 3.3.

Appreciate any suggestions.

eLRuLL
  • 18,488
  • 9
  • 73
  • 99
Ian Govett
  • 51
  • 6
  • 2
    Could you let us know what are you trying to test here. I dont see any method call here that uses mock connection. (You just set the mock behavior, not calling the close method) – PKR Sep 21 '16 at 15:34
  • 1
    Indeed, the code seems to correctly mock `Connection.close`. What problem do you encounter? – Henri Sep 21 '16 at 23:52
  • I updated the post to included a more complete example. – Ian Govett Sep 23 '16 at 13:05
  • Henri, I think the code should print the 'Close connection' text if the mock is working. – Ian Govett Sep 23 '16 at 13:09

0 Answers0