How would you test a Connection Pool

2019-02-03 12:11发布

问题:

I have implemented a very simple ConnectionPool in Java. It has no fancy features, just get/release connection methods.

How can I test it is working?

I know there are plenty of connection Pools ready to use out there, which are much more reliable than what I'll do, but I am just trying to practice to understand how connections Pool work.

Thank you!

Here is the code in case it helps:

public class ConnectionPoolImpl implements ConnectionPool {
    private Vector<PooledConnection> connections; // The connections container
    String url;
    String username; 
    String password;

    /**
     * Instanciates a new MySQLConnectionPool
     * @param nbConnectionsMax
     */
    public ConnectionPoolImpl(String DBUrl, String username, String password){
        this.connections = new Vector<PooledConnection>();
        this.url = DBUrl;
        this.username = username;
        this.password = password;
    }

    /**
     * Returns a connection from the pool, if some are available, or create a new one.
     * 
     * @return the connection.
     */
    public Connection getConnection() throws SQLException {
        synchronized(this.connections){
            // Checking if there is an available connection to return
            for(PooledConnection c : this.connections){
                if(!c.isUsed()){
                    c.setUsed();
                    return c.getConnection();
                }
            }

            // If there are none, open a new one and return it
            Connection conn = DriverManager.getConnection(url, username, password);
        PooledConnection pConn = new PooledConnection(conn);
        pConn.setUsed();
        connections.add(pConn);
        return pConn.getConnection();
        }
    }

    /**
     * Releases a connection to the pool.
     * 
     * @param con the connection to release.
     */
    public void releaseConnection(Connection con) throws SQLException {
        synchronized(this.connections){
            for(PooledConnection c : this.connections){
                if(c.getConnection().equals(con)){
                    c.setFree();
                    return;
                }
            }
        }
      }
}

And my PooledConnection.java:

public class PooledConnection {
    private Connection conn;
    private boolean used;

    public PooledConnection(Connection conn){
        this.conn = conn;
        this.used = false;
    }

    public void setUsed(){
        this.used = true;
    }

    public void setFree(){
        this.used = false;
    }

    public boolean isUsed(){
        return this.used;
    }

    public Connection getConnection(){
        return this.conn;
    }
}

回答1:

You could test that

  • getting a connection when the pool is empty gives you a connection
  • getting a connection when a connection has already been got and not released gives you another, different connection
  • releasing a connection doesn't throw any exception
  • getting a connection after one has been released gives you the same connection

Note that such a unit test would need a real database, with a real user and password to test. You could make your connection pool depend on a DataSource, and build your ConnectionPool using a mock DataSource returning mock Connections, in order to be able to test the class without depending on a real database.



回答2:

For an integration test, you could use dbUnit to load the database with prepared data and then write tests that query the database.

For an unit test, you might consider using a mocking library such as Mockito to ensure that you get the behaviour you expect. No database necessary in this case. [EDIT: However, due to the static method calls like DriverManager.getConnection(), this will require some refactoring and/or dependency injection.]

By combining both the unit tests and integration tests (and mix in some multi-threaded unit tests), you can go a long way towards testing your work.



回答3:

Industrial strength connection pools have the ability to check connections by making a connection and executing a simple SQL query (e.g. "SELECT 1") to ensure that connection is viable before giving it out. Yours does not.

I don't see where you can initialize the connection pool with a fixed number of connections. The whole point of a connection pool is to amortize the cost of creating a connection over all clients.

I'd worry about the design of your connection pool.

As for testing, just start writing unit tests. Since your pool will be shared, be sure to write some multi-threaded tests to make sure that it's really thread safe.



回答4:

You should also test concurrency/scalability under load using multiple threads.