Spring JUnit测试失败的原因是:org.postgresql.util。PSQLException:致命的:抱歉,已经有太多客户了。

时间:2021-12-03 23:04:31

If I run all my JUnit test cases at once (~300) I get the following Exception:

如果我一次运行所有的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)

In the postgres config (/etc/postgresql/9.2/main/postgresql.conf) the value is set to 100 as shown: max_connections = 100

在postgres配置(/etc/postgresql/9.2/main/postgresql.conf)中,该值设置为100,如下所示:max_connections = 100。

The Spring AppContext:

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

}

The DBUnit Database Connection:

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

Thinks I tried:

认为我尝试:

  • Change the setMaxPoolSize for c3p0 (from 1 to 100)

    更改c3p0的setMaxPoolSize(从1到100)

  • Increase max_connections in the postgres config (postgres didn't start up anymore)

    在postgres配置中增加max_connections (postgres不再启动)

  • Add Thread.sleep(1000); to @Before and @Before (1 to 10 Seconds)

    添加thread . sleep(1000);@Before和@Before(1 - 10秒)

If I run all the test often enough some times it will work, also when I only run a subset it works most of the time.

如果我经常运行所有的测试,有时它会起作用,而且当我只运行一个子集时,它大部分时间都在运行。

I'm also convinced that 100 database connections should be enough for 300 tests...

我还确信,100个数据库连接应该足够300个测试……

1 个解决方案

#1


0  

I found the Problem in the DBUnit Database Connection. It created a new Connection all the time.

我在DBUnit数据库连接中发现了这个问题。它一直在创造一种新的联系。

Now it behaves like a Singleton and the problem is gone.

现在它就像一个单例,问题已经解决了。

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

#1


0  

I found the Problem in the DBUnit Database Connection. It created a new Connection all the time.

我在DBUnit数据库连接中发现了这个问题。它一直在创造一种新的联系。

Now it behaves like a Singleton and the problem is gone.

现在它就像一个单例,问题已经解决了。

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