Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何测试连接池_Java_Unit Testing_Testing_Integration Testing_Connection Pooling - Fatal编程技术网

Java 如何测试连接池

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; //

我用Java实现了一个非常简单的ConnectionPool。 它没有奇特的特性,只是获取/释放连接方法

如何测试它是否正常工作

我知道有很多连接池可以使用,它们比我将要做的要可靠得多,但我只是想练习了解连接池是如何工作的

谢谢大家!

以下是代码,以防有帮助:

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;
    }
}