Java 如何测试连接池
我用Java实现了一个非常简单的ConnectionPool。 它没有奇特的特性,只是获取/释放连接方法 如何测试它是否正常工作 我知道有很多连接池可以使用,它们比我将要做的要可靠得多,但我只是想练习了解连接池是如何工作的 谢谢大家! 以下是代码,以防有帮助:Java 如何测试连接池,java,unit-testing,testing,integration-testing,connection-pooling,Java,Unit Testing,Testing,Integration Testing,Connection Pooling,我用Java实现了一个非常简单的ConnectionPool。 它没有奇特的特性,只是获取/释放连接方法 如何测试它是否正常工作 我知道有很多连接池可以使用,它们比我将要做的要可靠得多,但我只是想练习了解连接池是如何工作的 谢谢大家! 以下是代码,以防有帮助: public class ConnectionPoolImpl implements ConnectionPool { private Vector<PooledConnection> connections; //
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;
}
}
}
}
}
Industrial strength连接池能够通过建立连接并执行简单的SQL查询(例如“选择1”)来检查连接,以确保在发出连接之前连接是可行的。你的没有 我看不出在哪里可以使用固定数量的连接初始化连接池。连接池的全部要点是在所有客户端上分摊创建连接的成本 我会担心你的连接池的设计 至于测试,只需开始编写单元测试。由于您的池将被共享,请务必编写一些多线程测试,以确保它确实是线程安全的。您可以测试它
- 当池为空时获得连接将为您提供连接
- 当一个连接已经建立而没有被释放时,获得一个连接会给你另一个不同的连接
- 释放连接不会引发任何异常
- 在一个连接被释放后获得一个连接会给你相同的连接
请注意,这样的单元测试将需要一个真实的数据库,有一个真实的用户和密码进行测试。您可以使连接池依赖于数据源,并使用返回模拟连接的模拟数据源构建连接池,以便能够在不依赖真实数据库的情况下测试类。对于集成测试,您可以使用将准备好的数据加载到数据库中,然后编写查询数据库的测试
对于单元测试,您可以考虑使用嘲讽库,以确保获得所期望的行为。在这种情况下不需要数据库。[编辑:但是,由于DriverManager.getConnection()等静态方法调用,这将需要一些重构和/或依赖项注入。]
通过组合单元测试和集成测试(并混合一些多线程单元测试),您可以在测试工作方面取得很大进展 您还应该使用多线程测试负载下的并发性/可伸缩性。如果代码保持原样,Mockito将不会有帮助,因为它唯一的依赖项是DriverManager.getConnection静态方法,该方法不可模拟。这一点很好。它可能对一些重构/依赖注入有用。我将进行编辑。@JB Nizet,@Michael Easter:我尝试使用尽可能多的DI(例如,池连接不创建自己的连接,而是由构造函数提供一个连接。但是我想不出任何方法使ConnectionPool不依赖DriverManager.getConnection(),我该怎么做呢?不一定优雅,但这里有一种方法:定义一个名为Connectable的接口,它有一个getConnection()方法。编写DefaultConnectableImpl,它通过调用DriverManager.getConnection()来实现这个接口。现在,如果你的类在ctor中有一个可连接的,那么你就逃过了依赖关系。@Michael Easter:是的,几分钟前刚刚解决了这个问题,这是个好主意,现在我可以声明这个接口的一个模拟实现,并测试我的连接池,而大部分时间都没有真正的DB。仅供参考,你有一个bug。当你创建并重新创建打开一个新连接,您没有将其标记为已使用。@jtahlborn:Oops,您是对的。我在编辑中更正了这个问题。谢谢。谢谢您的建议。我是连接池的新手,所以请原谅我提出的这些问题,这些问题可能听起来很愚蠢:1.我同意最大连接数非常重要,我应该添加一个,但我不同意你是说我应该在ConnectionPool的实例化过程中打开固定数量的连接,还是应该一个接一个地创建它们(就像我现在做的那样)直到达到最大值?2.当达到最大值且线程请求连接时,最好返回null,还是等待连接释放并返回?-3.拥有连接池的要点之一不是每次线程想要联系D时都要花费时间打开和关闭连接吗B?如果是,在释放连接之前是否检查连接的方向相反?非常感谢!我建议根据最小值创建多个连接,然后根据需要添加更多连接。如果请求另一个连接,您可以选择创建新连接或等待另一个连接被释放。使用con连接不是问题;创建连接才是问题。你不关闭连接,只需将其放回池中。在发布之前检查连接是所有商业和开源池都允许你做的事情,因此我猜这不会朝相反的方向发展。nbarlaille,你可能想开始一个单独的问题,“评论我的连接池”或“我将如何设计连接池?”。这篇文章很有趣,但几乎没有回答“如何测试它?”。
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;
}
}