2013-07-17 2 views
2

Мне нужно выполнить интеграционные тесты с использованием DbUnit. Я создал набор данных (до и после теста) и сравнил их, используя @DatabaseSetup и @ExpectedDatabase аннотации. Во время теста была создана одна новая строка базы данных (она представлена ​​после набора тестовых данных, которую я указываю с помощью аннотации @ExpectedDatabase). Проблема в том, что идентификатор строки генерируется автоматически (я использую Hibernate), поэтому идентификатор строки постоянно меняется. Поэтому мой тест проходит только один раз, после чего мне нужно изменить идентификатор после набора тестовых данных, но это не то, что мне нужно. Можете ли вы предложить мне любые решения для этой проблемы, если эта проблема может быть решена с помощью DbUnit.DbUnit check autogenerating id

+0

Я встретил подобные проблемы, вы разработали решение для их решения? – ReturnHttp402

+0

Я проигнорировал утверждение id. См. Решение B (ответ ниже). Для моих тестовых случаев такое утверждение не было существенным. – mvb13

+0

Как вы интегрируете assertEqualsIngoreColumns() в аннотации? Кстати, я также обнаружил, что использование базы данных в памяти в базе данных, подключенной к источнику данных, также является альтернативным выбором для db in-памяти, который будет выполнять инициализацию каждый раз при запуске теста. – ReturnHttp402

ответ

2

Раствор А:

Использование присваивается идентификатор стратегии и использовать отдельный запрос для получения следующего значения в бизнес-логике. Таким образом, вы всегда можете назначить известный идентификатор в тестах на постоянство с некоторой соответствующей очисткой базы данных. Обратите внимание, что это работает, только если вы используете Oracle Sequence.

Раствор Б:

Если я не ошибаюсь, есть некоторые методы, аналогичные assertEqualsIngoreColumns() в org.dbunit.Assertion. Поэтому вы можете игнорировать утверждение id, если не возражаете. Обычно я компенсирую это, если не проверять идентификатор. Возможно, есть некоторые варианты в @ExpectedDatabase, но я не уверен.

Решения C:

Я хотел бы знать, если есть лучшее решение, потому что раствор А вводят некоторые накладные расходы на производительность в то время как решение B жертвует немного тестовое покрытие.

Какая версия dbunit вы используете, кстати. Я никогда не видел эти аннотации в 2.4.9 и ниже, они выглядят более простыми в использовании.

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

С этим можно как-то отслеживать идентификаторы вам нужно, и заменить в ваших яичках

@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>