Spring Test DBunit Warning

2019-04-05 01:40发布

问题:

I am using spring-test-dbunit and I get a warning in my Unit tests with this message:

Code:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/context.xml"})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class,
    TransactionalTestExecutionListener.class,
    DbUnitTestExecutionListener.class })
public class TestDB {

    @Autowired 
    private ICourseService courseService;

    @Test
    @DatabaseSetup("sampleData.xml")
    public void testFind() throws Exception {
        List<Course> courseList = this.courseService.getAllCourses();

        assertEquals(1, courseList.size());
        assertEquals("A001", courseList.get(0).getCourseNumber());
    }

}

Warning:

1093 [main] WARN org.dbunit.dataset.AbstractTableMetaData - Potential problem found: The configured data type factory 'class org.dbunit.dataset.datatype.DefaultDataTypeFactory' might cause problems with the current database 'MySQL' (e.g. some datatypes may not be supported properly). In rare cases you might see this message because the list of supported database products is incomplete (list=[derby]). If so please request a java-class update via the forums.If you are using your own IDataTypeFactory extending DefaultDataTypeFactory, ensure that you override getValidDbProducts() to specify the supported database products.

The problem can be solved when I use DBunit without spring-test-dbunit as follow:

  Connection jdbcConnection = DriverManager.getConnection( "jdbc:mysql://localhost/test", "root", "root");
        IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);
        connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory());
        connection.getConfig().setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MySqlMetadataHandler());

I don't know how to solve this problem in spring-test-dbunit. Please help.

回答1:

Problem solved. I add the following configuration to applicationContext.xml (context.xml) .

<property name="location">
        <value>classpath:jdbc.properties</value>
    </property> 
</bean>  

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${driver}" />
    <property name="url" value="${url}" />
    <property name="username" value="${username}" />
    <property name="password" value="${password}" />
</bean>

<bean id="sqlDataTypeFactory" class ="org.dbunit.ext.mysql.MySqlDataTypeFactory" />

<bean id="dbUnitDatabaseConfig" class="com.github.springtestdbunit.bean.DatabaseConfigBean">
     <property name = "datatypeFactory" ref = "sqlDataTypeFactory" />
</bean> 
<bean id="dbUnitDatabaseConnection" class="com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean">
    <property name="databaseConfig" ref="dbUnitDatabaseConfig"/>
    <property name="dataSource" ref="dataSource" />
</bean>


回答2:

Just wanted to add the same solution as Java Config:

@Bean
public DataSource dataSource() {
    DataSource dataSource = ...
    return dataSource;
}

@Bean
public DatabaseConfigBean dbUnitDatabaseConfig() {
    DatabaseConfigBean dbConfig = new com.github.springtestdbunit.bean.DatabaseConfigBean();
    dbConfig.setDatatypeFactory(new org.dbunit.ext.h2.H2DataTypeFactory());
    return dbConfig;
}

@Bean
public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnection() {
    DatabaseDataSourceConnectionFactoryBean dbConnection = new com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean(dataSource());
    dbConnection.setDatabaseConfig(dbUnitDatabaseConfig());
    return dbConnection;
}


回答3:

To complement the existing answers, I just wanted to add what worked for me in a Spring Boot context, using the Spring Boot configured datasource. Add the following class in your test sources (in a package that will be picked up by autoconfig) :

@Configuration
public class DBUnitConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnection() {
        DatabaseConfigBean bean = new DatabaseConfigBean();
        bean.setDatatypeFactory(new H2DataTypeFactory());

        DatabaseDataSourceConnectionFactoryBean dbConnectionFactory = new com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean(dataSource);
        dbConnectionFactory.setDatabaseConfig(bean);
        return dbConnectionFactory;
    }
}


回答4:

Thanks to Lynn Niño. The answer helped me to correct the configuration for my H2 Database:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <context:component-scan base-package="isi.power.share" />

    <tx:annotation-driven transaction-manager="transactionManager" />

    <!-- H2 database JDBC settings -->    
    <bean id="dataSource"
          class="org.h2.jdbcx.JdbcDataSource">
        <property name="URL" value="jdbc:h2:mem:paging;DB_CLOSE_DELAY=-1;MODE=MySQL;INIT=CREATE SCHEMA IF NOT EXISTS my_extra_schema;"/>
        <property name="user" value="root"/>
        <property name="password" value="password"/>
    </bean>    

    <!-- set the data type factory for dbunit -->
    <bean id="h2DataTypeFactory" class ="org.dbunit.ext.h2.H2DataTypeFactory" />

    <bean id="dbUnitDatabaseConfig" class="com.github.springtestdbunit.bean.DatabaseConfigBean"> 
         <property name = "datatypeFactory" ref = "h2DataTypeFactory" /> 
    </bean>  

    <bean id="dbUnitDatabaseConnection" class="com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean"> 
        <property name="databaseConfig" ref="dbUnitDatabaseConfig"/> 
        <property name="dataSource" ref="dataSource" /> 
    </bean> 

    <!-- provide a H2 console to look into the db if necessary -->
    <bean id="org.h2.tools.Server-WebServer" class="org.h2.tools.Server"
        factory-method="createWebServer" depends-on="dataSource"
        init-method="start" lazy-init="false">
        <constructor-arg value="-web,-webAllowOthers,-webPort,8085" />
    </bean>

    <!-- provide a TCP server to look into the db if necessary -->
    <bean id="org.h2.tools.Server-TcpServer" class="org.h2.tools.Server"
        factory-method="createTcpServer" depends-on="dataSource"
        init-method="start" lazy-init="false">
        <constructor-arg value="-tcp,-tcpAllowOthers,-tcpPort,9095" />
    </bean>

    <!-- define database entity manager factory & transaction manager -->

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
        <property name="persistenceXmlLocation"  value="classpath:META-INF/SpringDatabaseTestPersistence.xml" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />     
    </bean>


</beans>