簡體   English   中英

春季JUnit測試失敗,原因是:org.postgresql.util.PSQLException:FATAL:對不起,已經有太多客戶端了

[英]Spring JUnit Test fail caused by: org.postgresql.util.PSQLException: FATAL: sorry, too many clients already

如果我一次運行所有的JUnit測試用例(〜300),則會收到以下異常:

org.postgresql.util.PSQLException: FATAL: sorry, too many clients already
    at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:293)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:108)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66)
    at org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:125)
    at org.postgresql.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:30)
    at org.postgresql.jdbc3g.AbstractJdbc3gConnection.<init>(AbstractJdbc3gConnection.java:22)
    at org.postgresql.jdbc4.AbstractJdbc4Connection.<init>(AbstractJdbc4Connection.java:32)
    at org.postgresql.jdbc4.Jdbc4Connection.<init>(Jdbc4Connection.java:24)
    at org.postgresql.Driver.makeConnection(Driver.java:393)
    at org.postgresql.Driver.connect(Driver.java:267)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    at test.testingTools.DatabaseConnector.getTestConnection(DatabaseConnector.java:24)
    at test.repository.cascade.merge_persist.ParentCascadeMPTest.setUp(ParentCascadeMPTest.java:56)
    at sun.reflect.GeneratedMethodAccessor73.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

在postgres配置(/etc/postgresql/9.2/main/postgresql.conf)中,該值設置為100,如下所示:max_connections = 100

Spring AppContext:

package test;

import java.beans.PropertyVetoException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.hibernate.dialect.PostgreSQL9Dialect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableLoadTimeWeaving;
import org.springframework.context.annotation.EnableLoadTimeWeaving.AspectJWeaving;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.aspectj.EnableSpringConfigured;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import com.mchange.v2.c3p0.AbstractComboPooledDataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;

@Configuration
@EnableSpringConfigured
@EnableLoadTimeWeaving(aspectjWeaving = AspectJWeaving.ENABLED)
@ComponentScan(basePackages = { "test" })
@PropertySource("META-INF/spring/props.properties")
@EnableJpaRepositories("test.repository")
public class AppContext {

    @Autowired
    private Environment env;
    @Autowired
    private DataSource dataSource;

    @Bean(name = "dataSource", destroyMethod = "close")
    @Profile("test")
    public DataSource dataSourceTest() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(env.getProperty("testDb.driverClass"));
        dataSource.setJdbcUrl(env.getProperty("testDb.jdbcUrl"));
        dataSource.setUser(env.getProperty("testDb.user"));
        dataSource.setPassword(env.getProperty("testDb.password"));
        setDataSourceProperties(dataSource);
        return dataSource;
    }

    // use this to configure c3p0
    /*
     * with the @Repeat annotation from springframework.test at a test connecting to the test database, a PSQLException
     * for too many clients can easily be reproduced to try out new configuration parameters
     */
    private void setDataSourceProperties(AbstractComboPooledDataSource dataSource) {
        dataSource.setAcquireIncrement(5);
        dataSource.setMinPoolSize(5);
        dataSource.setMaxPoolSize(100);
    }

    @Bean
    public Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<String, Object>();
        props.put("hibernate.dialect", PostgreSQL9Dialect.class.getName());
        return props;
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setShowSql(false);
        hibernateJpaVendorAdapter.setGenerateDdl(true);
        hibernateJpaVendorAdapter.setDatabase(Database.POSTGRESQL);
        return hibernateJpaVendorAdapter;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new JpaTransactionManager(entityManagerFactory().getObject());
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setDataSource(this.dataSource);
        emf.setJpaPropertyMap(this.jpaProperties());
        emf.setJpaVendorAdapter(this.jpaVendorAdapter());
        emf.setPackagesToScan("test");
        return emf;
    }

}

DBUnit數據庫連接:

package test;

import java.sql.Connection;
import java.sql.DriverManager;

import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.springframework.stereotype.Component;

@Component
public class DatabaseConnector {

    public DatabaseConnector() {

    }

    public IDatabaseConnection getTestConnection() throws Exception {

        Connection dbConnection = null;

        Class.forName("org.postgresql.Driver");

        dbConnection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/test", "user", "password");

        IDatabaseConnection connection = new DatabaseConnection(dbConnection);

        return connection;
    }
}

認為我嘗試過:

  • 更改c3p0的setMaxPoolSize(從1到100)

  • 在postgres配置中增加max_connections(postgres不再啟動)

  • 添加Thread.sleep(1000); 到@Before和@Before(1到10秒)

如果我經常運行所有測試幾次,它將可以正常工作,而當我僅運行一個子集時,大部分時間也可以運行。

我還堅信100個數據庫連接應該足以進行300個測試...

我在DBUnit數據庫連接中發現了問題。 它一直創建一個新的Connection。

現在它的行為像Singleton,問題已經解決了。

package test.testingTools;

import java.sql.Connection;
import java.sql.DriverManager;

import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.springframework.stereotype.Component;

@Component
public class DatabaseConnector {

    IDatabaseConnection connection;

    public DatabaseConnector() throws Exception {
        Connection dbConnection = null;

        Class.forName("org.postgresql.Driver");

        dbConnection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/test", "user", "password");

        connection = new DatabaseConnection(dbConnection);

    }

    public IDatabaseConnection getTestConnection() {

        return connection;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM