我需要使用DbUnit执行集成测试。我创建了数据集(测试前后),并使用@DatabaseSetup
和@ExpectedDatabase
注释进行比较。在测试期间,创建了一个新的数据库行(它显示在测试数据集之后,我使用@ExpectedDatabase
注释指定)。问题是行id是自动生成的(我正在使用Hibernate),因此行ID会永久更改。因此我的测试只传递一次,之后我需要在测试数据集之后更改id,但这不是我需要的。如果可以使用DbUnit解决此问题,您能否建议我解决此问题的任何解决方案。
答案 0 :(得分:2)
解决方案A:
使用已分配的ID策略并使用单独的查询来检索业务逻辑中的下一个值。因此,您始终可以使用适当的数据库清理在持久性测试中分配已知的ID。请注意,这只适用于您使用Oracle序列。
解决方案B:
如果我没有弄错,有一些方法类似于org.dbunit.Assertion中的assertEqualsIngoreColumns()。如果你不介意的话,你可以忽略id断言。通常我会通过对id进行非空检查来弥补这一点。也许@ExpectedDatabase中有一些选项,但我不确定。
解决方案C:
我想知道是否有更好的解决方案,因为解决方案A会引入一些性能开销,而解决方案B会牺牲一点测试覆盖率。
顺便提一下,您使用的是哪个版本的dbunit。我在2.4.9及以下版本中从未见过这些注释,它们看起来更容易使用。
答案 1 :(得分:0)
这种解决方法一直在拯救我的皮肤:
我实现了一个具有替换功能的AbstractDataSetLoader:
public class ReplacerDataSetLoader extends AbstractDataSetLoader {
private Map<String, Object> 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));
}
}
/**
* prepare some replacements
* @param dataSet
* @return
*/
private ReplacementDataSet createReplacementDataSet(FlatXmlDataSet dataSet) {
ReplacementDataSet replacementDataSet = new ReplacementDataSet(dataSet);
//Configure the replacement dataset to replace '[null]' strings with null.
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<String, Object> entry : replacements.entrySet()) {
replacementDataSet.addReplacementObject("["+entry.getKey()+"]", entry.getValue());
}
replacements.clear();
return replacementDataSet;
}
public void replace(String replacement, Object value){
replacements.put(replacement, value);
}
}
通过这种方式,您可以以某种方式跟踪您需要的ID并替换您的睾丸
@DatabaseSetup(value="/test_data_user.xml")
@DbUnitConfiguration(dataSetLoaderBean = "replacerDataSetLoader")
public class ControllerITest extends WebAppConfigurationAware {
//reference my test dbconnection so I can get last Id using regular query
@Autowired
DatabaseDataSourceConnection dbUnitDatabaseConnection;
//reference my datasetloader so i can iteract with it
@Autowired
ColumnSensingFlatXMLDataSetLoader datasetLoader;
private static Number lastid = Integer.valueOf(15156);
@Before
public void setup(){
System.out.println("setting "+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{
//run your test logic
}
@Test
@ExpectedDatabase(value="/expected_data.xml", assertionMode=DatabaseAssertionMode.NON_STRICT)
public void test2() throws Exception{
//run your test logic
}
}
我的预期数据集需要替换emp1和emp2
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<company.entity_group ID="15155" corporate_name="comp1"/>
<company.entity_group ID="15156" corporate_name="comp2"/>
<company.entity_group ID="[emp1]" corporate_name="comp3"/>
<company.entity_group ID="[emp2]" corporate_name="comp3"/>
<company.ref_entity ID="1" entity_group_id="[emp1]"/>
<company.ref_entity ID="2" entity_group_id="[emp2]"/>
</dataset>
答案 2 :(得分:0)
使用DatabaseAssertionMode.NO_STRICT,并删除&#39; id&#39;来自&#39; expect.xml&#39;的列。 DBUnit将忽略此列。