2 Stimmen

DbUnit überprüfen automatische Id-Generierung

Ich muss Integrationstests mit DbUnit ausführen. Ich habe zwei Datensätze erstellt (vor und nach dem Test) und vergleiche sie mit den Annotationen @DatabaseSetup und @ExpectedDatabase. Während des Tests wurde eine neue Datenbankzeile erstellt (die im Datensatz nach dem Test vorhanden ist, den ich mit der Annotation @ExpectedDatabase angebe). Das Problem ist, dass die Zeilen-ID automatisch generiert wird (ich verwende Hibernate), daher ändert sich die ID dauerhaft. Daher besteht mein Test nur einmal und danach muss ich die ID im Datensatz nach dem Test ändern, aber das ist nicht das, was ich brauche. Können Sie mir bitte Lösungen für dieses Problem vorschlagen, falls dieses Problem mit DbUnit gelöst werden kann.

2voto

Yugang Zhou Punkte 7023

Lösung A:

Verwenden Sie die zugewiesene ID-Strategie und verwenden Sie eine separate Abfrage, um den nächsten Wert in der Geschäftslogik abzurufen. So können Sie immer eine bekannte ID in Ihren Persistenztests mit einer geeigneten Datenbankbereinigung zuweisen. Beachten Sie, dass dies nur funktioniert, wenn Sie Oracle Sequence verwenden.

Lösung B:

Wenn ich mich nicht irre, gibt es einige Methoden ähnlich wie assertEqualsIngoreColumns() in org.dbunit.Assertion. So können Sie die ID-Assertion ignorieren, wenn es Ihnen nichts ausmacht. Normalerweise kompensiere ich das mit einem not Null-Check auf die ID. Vielleicht gibt es einige Optionen in @ExpectedDatabase, aber ich bin mir nicht sicher.

Lösung C:

Ich würde gerne wissen, ob es eine bessere Lösung gibt, da Lösung A einige Leistungseinbußen mit sich bringt, während Lösung B die Testabdeckung etwas beeinträchtigt.

Übrigens, welche Version von dbunit verwenden Sie? Ich habe diese Annotationen noch nie in Version 2.4.9 und darunter gesehen, sie scheinen einfacher zu sein.

0voto

Warley Noleto Punkte 493

Das Workaround hat mir bisher geholfen:

Ich implementierte einen AbstractDataSetLoader mit Ersetzungsfunktion:

public class ReplacerDataSetLoader extends AbstractDataSetLoader {
    private Map replacements = new ConcurrentHashMap<>();

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

    /**
     * Bereite einige Ersetzungen vor
     * @param dataSet
     * @return
     */
    private ReplacementDataSet createReplacementDataSet(FlatXmlDataSet dataSet) {
        ReplacementDataSet replacementDataSet = new ReplacementDataSet(dataSet);

        //Konfiguriere das Ersetzungsdatenset, um '[null]'-Zeichenfolgen durch null zu ersetzen.
        replacementDataSet.addReplacementObject("[null]", null);
        replacementDataSet.addReplacementObject("[NULL]", null);
        replacementDataSet.addReplacementObject("[TODAY]", new Date());
        replacementDataSet.addReplacementObject("[NOW]", new Timestamp(System.currentTimeMillis()));

        for (java.util.Map.Entry entry : replacements.entrySet()) {
            replacementDataSet.addReplacementObject("["+entry.getKey()+"]", entry.getValue());
        }
        replacements.clear();

        return replacementDataSet;
    }

    public void replace(String replacement, Object value){
        replacements.put(replacement, value);
    }
}

So können Sie die IDs, die Sie benötigen, irgendwie verfolgen und in Ihren Tests ersetzen

@DatabaseSetup(value="/test_data_user.xml")
@DbUnitConfiguration(dataSetLoaderBean = "replacerDataSetLoader")
public class ControllerITest extends WebAppConfigurationAware {

    //Beziehe meine Test-DB-Verbindung, um die letzte ID mit einer regulären Abfrage zu erhalten
    @Autowired
    DatabaseDataSourceConnection dbUnitDatabaseConnection;
    //Beziehe meinen DatasetLoader, um damit zu interagieren
    @Autowired
    ColumnSensingFlatXMLDataSetLoader datasetLoader;

    private static Number lastid = Integer.valueOf(15156);
    @Before
    public void setup(){
        System.out.println("Einstellung "+lastid);
        datasetLoader.replace("emp1", lastid.intValue()+1);
        datasetLoader.replace("emp2", lastid.intValue()+2);
    }

    @After
    public void tearDown() throws SQLException, DataSetException{
        ITable table = dbUnitDatabaseConnection.createQueryTable("ids", "select max(id) as id from company.entity_group");
        lastid = (Number)table.getValue(0, "id");
    }

    @Test
    @ExpectedDatabase(value="/expected_data.xml", assertionMode=DatabaseAssertionMode.NON_STRICT)
    public void test1() throws Exception{
        //Führen Sie Ihre Testlogik aus
    }

    @Test
    @ExpectedDatabase(value="/expected_data.xml", assertionMode=DatabaseAssertionMode.NON_STRICT)
    public void test2() throws Exception{
        //Führen Sie Ihre Testlogik aus
    }
}

Und mein erwartetes Dataset benötigt einige Ersetzungen von emp1 und emp2

0voto

Junhong Wu Punkte 1

Verwenden Sie DatabaseAssertionMode.NO_STRICT und löschen Sie die 'id'-Spalte aus Ihrer 'expect.xml'. DBUnit wird diese Spalte ignorieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X