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.
Antworten
Zu viele Anzeigen?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.
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