Project

General

Profile


How to write IntegrationTests and how to generate test data for them

Related pages:


CdmTransactionalIntegrationTest

In most cases you may want your test to be subclass of CdmTransactionalIntegrationTest

After a test method is run the transaction is usually rolled back.

If you need something to be really persisted into the data base call the commitAndStartNewTransaction()

method after the service.saveOrUpdate(Someting)

dbUnit test data

Unitils provides integation with DbUnit wich support for testing with databases and loading of DbUnit data sets. DbUnit is a JUnit extension (also usable with Ant) targeted at database-driven projects that, among other things, puts your database into a known state between test runs. This is an excellent way to avoid the myriad of problems that can occur when one test case corrupts the database and causes subsequent tests to fail or exacerbate the damage.

Test dependencies and load strategy

Even if DbUnit should turn your database into a known and controlled state it can happen that the database contains leftovers from previous tests. In order to explicitly wipe out all potential remains you can in case use specific load strategy class, the CleanSweepInsertLoadStrategy which will provide you a really virgin database:

@Test
@DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
public void testArea_area() throws FileNotFoundException {
  // your test
}

Generating test data

The DbUnit datasets in the cdm library are provided as flat xml data files. This is quite nice until it comes to extending test or to refactoring library code.

In this case it can become very time consuming and painful to adapt the flat xml data files accordingly. Therefore it is highly recommended to generate the test data from within the test class itself like in the following little example:

// @Test //  uncomment and run this test method to create/update the flat xml test data file
public void createTestData() throws FileNotFoundException {

        // --- References --- //
        Reference sec = ReferenceFactory.newDatabase();
        sec.setTitleCache("Test", true);
        Reference nomRef = ReferenceFactory.newBook();
        sec.setTitleCache("Sp.Pl.", true);

        referenceService.save(sec);
        referenceService.save(nomRef);

        BotanicalName n_lapsana = BotanicalName.NewInstance(Rank.GENUS());
        n_lapsana.setTitleCache("Lapsana", true);
        Taxon t_lapsana = Taxon.NewInstance(n_lapsana, sec);
        t_lapsana.setUuid(T_LAPSANA_UUID);
        taxonService.saveOrUpdate(t_lapsana);

        // create more entities like classification, ....

    commitAndStartNewTransaction(null);

        // this will write flat xml file to the same package in the test resources 
        // the test file is named after the test class like: TestClassName.xml
    writeDbUnitDataSetFile(new String[] {
            "TAXONBASE", "TAXONNAMEBASE",
            "REFERENCE", "DESCRIPTIONELEMENTBASE", "DESCRIPTIONBASE",
            "AGENTBASE", "CLASSIFICATION", "TAXONNODE",
            "HOMOTYPICALGROUP", "LANGUAGESTRING",
     });
}

But be CAREFUL. This will overwrite existing dataset files.

Null values

Are expressed by [null], e.g.

<AGENTBASE DTYPE="Person" LIFESPAN_END="[null]"/>

Term loading in tests

Terms for tests are loaded by the TestingTermInitializer it loads the terms from flast xml data files. This assures that tests can rely on fixed term ids in the datbase.

Otherwise most test data in the xml files would be broken after adding or removing terms in the cdmlib.

The files to load are configured in the test application context:

    <bean id="termInitializer" class="eu.etaxonomy.cdm.database.TestingTermInitializer">
        <property name="termsDataSet" value="classpath:/eu/etaxonomy/cdm/database/TermsDataSet-with_auditing_info.xml"/>
        <property name="termsDtd" value="classpath:/eu/etaxonomy/cdm/persistence/dao/hibernate/dataset.dtd"/>
    </bean>
Add picture from clipboard (Maximum size: 40 MB)