DBUnit测试为MariaDB提供NoSuchColumnException

时间:2018-06-15 16:06:57

标签: java spring windows mariadb dbunit

重要的是要注意这些测试在Ubuntu和服务器上运行良好,但在Mac和Windows上失败并出现相同的错误。

因此,在我的测试中,我使用此配置连接到Maria db:

@Configuration
public class EmbeddedDatabase {

    @Autowired
    private String defaultSchema;

    @Bean
    public MariaDB4jService mariaDB4jService() {
        MariaDB4jSpringService mariaDB4jSpringService = new MariaDB4jSpringService();

        DBConfigurationBuilder config = mariaDB4jSpringService.getConfiguration();
        config.setPort(3310);

        return mariaDB4jSpringService;
    }

    @Bean
    public DataSource dataSource(MariaDB4jService mariaDB4jService) throws Exception {
        mariaDB4jService.getDB().createDB(defaultSchema);

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(mariaDB4jService.getConfiguration().getURL(defaultSchema));
        dataSource.setUsername("root");
        dataSource.setPassword("");
        dataSource.setDriverClassName("org.mariadb.jdbc.Driver");

        return dataSource;
    }
}

现在,我的xml配置文件中设置了默认架构,它是:

<bean id="dbUnitDatabaseConnection" class="com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean" 
    <property name="schema" ref="defaultSchema" />
    <property name="dataSource" ref="dataSource"/>
</bean>
<bean id="defaultSchema" class="java.lang.String">
    <constructor-arg type="java.lang.String" value="test"/>
</bean>

以下是所有测试类的父类:

@ContextConfiguration("classpath:test-repository-config.xml")
@TestExecutionListeners({ DbUnitTestExecutionListener.class })
@DbUnitConfiguration(dataSetLoader = RepositoryFlatXmlDataSetLoader.class)
public abstract class AbstractRepositoryTest 
    extends AbstractTransactionalJUnit4SpringContextTests {

}

我有这个自定义的RepositoryFlatXmlDataSetLoader用于替换&#34; [NULL]&#34;我在xml数据集中使用的字段:

public class RepositoryFlatXmlDataSetLoader extends AbstractDataSetLoader {
    private static Logger logger = LoggerFactory.getLogger(RepositoryFlatXmlDataSetLoader.class);
    @Override
    protected IDataSet createDataSet(Resource resource) throws Exception {
        FlatXmlDataSetBuilder builder = new FlatXmlDataSetBuilder();
        builder.setColumnSensing(true);

        try (InputStream inputStream = resource.getInputStream()) {
            return createReplacementDataSet(builder.build(inputStream));            
        }
        catch(Throwable thrh){
            logger.error("Failed to create dataset");
            throw thrh;
        }
    }

    private ReplacementDataSet createReplacementDataSet(FlatXmlDataSet dataSet) {
        ReplacementDataSet replacementDataSet = new ReplacementDataSet(dataSet);

        //Configure the replacement dataset to replace '[null]' strings with null.
        replacementDataSet.addReplacementObject("[null]", ITable.NO_VALUE);
        replacementDataSet.addReplacementObject("[NULL]", ITable.NO_VALUE);

        return replacementDataSet;
    }
}

这是我的数据集xml文件之一 - officeRepositoryData.xml:

<dataset>
    <cfr_office ID="1" ORG_NAME="demo" IS_DEFAULT="true"/>
    <cfr_office ID="2" ORG_NAME="test" IS_DEFAULT="false"/>
</dataset>

例如,这是其中一项测试:

@NotThreadSafe
@DatabaseSetup(value = "officeRepositoryData.xml", type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(value = "officeRepositoryData.xml", type = DatabaseOperation.DELETE_ALL)
public class OfficeRepositoryTest extends AbstractRepositoryTest {

    @Autowired
    private OfficeRepository officeRepository;

    @Test
    public void testDefaultOfficeFound() {
        List<Office> offices = officeRepository.findDefault();

        assertTrue(isNotEmpty(offices));

        Office office = offices.get(0);
        assertEquals("demo", office.getOrganizationName());
        assertTrue(office.getIsDefault());
    }
}

那么,当我运行测试时会发生什么...... 所有表都是在JPA中创建的,我在eclipse控制台和DB Perspective中看到它创建了MariaDB连接,然后当dbUnit开始为测试准备数据集时,我得到一个错误。这是它的堆栈跟踪,其中一些先前的行可能很重要(或不是,不确定):

INFO  o.s.t.c.t.TransactionContext - Began transaction (1) for test context [DefaultTestContext@305e95a4 testClass = OfficeRepositoryTest, testInstance = com.sumac.nots.repository.api.OfficeRepositoryTest@55e42684, testMethod = testDefaultOfficeFound@OfficeRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@2a5c6b76 testClass = OfficeRepositoryTest, locations = '{classpath:test-repository-config.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@7f22687e]; rollback [true]
11:49:33.775 [main] WARN  o.d.d.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.
11:49:42.306 [main] WARN  o.d.d.DatabaseTableMetaData - No columns found for table 'cfr_office' that are supported by dbunit. Will return an empty column list
11:49:48.098 [main] WARN  o.s.t.c.TestContextManager - Caught exception while allowing TestExecutionListener [com.github.springtestdbunit.DbUnitTestExecutionListener@66d3eec0] to process 'before' execution of test method [public void com.sumac.nots.repository.api.OfficeRepositoryTest.testDefaultOfficeFound()] for test instance [com.sumac.nots.repository.api.OfficeRepositoryTest@55e42684]
org.dbunit.dataset.NoSuchColumnException: cfr_office.ID -  (Non-uppercase input column: ID) in ColumnNameToIndexes cache map. Note that the map's column names are NOT case sensitive.
    at org.dbunit.dataset.AbstractTableMetaData.getColumnIndex(AbstractTableMetaData.java:117)
    at org.dbunit.operation.AbstractOperation.getOperationMetaData(AbstractOperation.java:89)
    at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:150)
    at org.dbunit.operation.CompositeOperation.execute(CompositeOperation.java:79)
    at com.github.springtestdbunit.DbUnitRunner.setupOrTeardown(DbUnitRunner.java:183)
    at com.github.springtestdbunit.DbUnitRunner.beforeTestMethod(DbUnitRunner.java:75)
    at com.github.springtestdbunit.DbUnitTestExecutionListener.beforeTestMethod(DbUnitTestExecutionListener.java:185)
    at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:269)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:539)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)

通常对于这样的错误,原因是列错过某处或列有一些区分大小写问题,我在代码中进行了深度调试,而且在我看来,对于这个特殊情况我遇到了一些其他问题。但我不确定。

看起来深入代码dbUnit会创建一些columnList,从某些resultSet获取有关db的一些信息。如果所有信息都与catalog,schema_name和table_name匹配,则会感觉此列列表中包含列值。但是shema_name在调试中为null,因此无法创建列列表,然后无法在那里找到第一列 - 即ID。 如果我写的最后一段是一团糟,不要把它计算在内。

1 个答案:

答案 0 :(得分:0)

我会尝试使用小写列名:

<dataset>
    <cfr_office id="1" org_name="demo" is_default="true"/>
    <cfr_office id="2" org_name="test" is_default="false"/>
</dataset>