Очистка базы данных после тестов Junit

Я должен протестировать некоторые сервисы Thrift, используя Junit. Когда я запускаю свои тесты в качестве клиента Thrift, сервисы изменяют базу данных сервера. Я не могу найти хорошее решение, которое может очистить базу данных после каждого теста. Очистка важна особенно потому, что идентификаторы должны быть уникальными, которые в настоящее время считываются из файла XML. Теперь я должен вручную изменить идентификаторы после запуска тестов, чтобы следующий набор тестов мог выполняться без выброса нарушения первичного ключа в базу данных. Если я смогу очистить базу данных после каждого запуска теста, тогда проблема будет полностью решена, иначе мне придется подумать о других решениях, таких как генерация случайных идентификаторов и их использование везде, где требуются идентификаторы.

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

12
задан Ashish 13 August 2010 в 06:28
поделиться

8 ответов

Если вы не тестируете определенные действия с базой данных (например, проверяете, можете ли вы запрашивать или обновлять базу данных), ваши JUnits не должны писать в настоящую базу данных. Вместо этого вы должны издеваться над классами базы данных. Таким образом, вам фактически не нужно подключать и изменять базу данных, и, следовательно, не требуется очистка.

Вы можете издеваться над своими классами несколькими способами. Вы можете использовать такую ​​библиотеку, как JMock , которая сделает за вас всю работу по выполнению и проверке. Лично мне больше всего нравится делать это с помощью внедрения зависимостей. Таким образом, я могу создавать фиктивные классы, которые реализуют интерфейсы моего репозитория (вы правильно используете интерфейсы для своего уровня доступа к данным? ;-)), и я реализую только необходимые методы с известными действиями / возвращаемыми значениями.

//Example repository interface.
public interface StudentRepository
{
   public List<Student> getAllStudents();
}

//Example mock database class.
public class MockStudentRepository implements StudentRepository
{
   //This method creates fake but known data.
   public List<Student> getAllStudents()
   {
      List<Student> studentList =  new ArrayList<Student>();
      studentList.add(new Student(...));
      studentList.add(new Student(...));
      studentList.add(new Student(...));

      return studentList;
   }
}

//Example method to test.
public int computeAverageAge(StudentRepository aRepository)
{
   List<Student> students = aRepository.GetAllStudents();
   int totalAge = 0;
   for(Student student : students)
   {
      totalAge += student.getAge();
   }

   return totalAge/students.size();
}

//Example test method.
public void testComputeAverageAge()
{
   int expectedAverage = 25; //What the expected answer of your result set is
   int actualAverage = computeAverageAge(new MockStudentRepository());

   AssertEquals(expectedAverage, actualAverage);
}
7
ответ дан 2 December 2019 в 03:48
поделиться

Как насчет использования чего-то вроде DBUnit ?

5
ответ дан 2 December 2019 в 03:48
поделиться

Среда модульного тестирования Spring имеет обширные возможности для работы с JDBC. Общий подход заключается в том, что модульные тесты выполняются в транзакции, и (за пределами вашего теста) транзакция откатывается после завершения теста.

Это дает возможность использовать вашу базу данных и ее схему, но без внесения каких-либо прямых изменений в данные. Конечно, если вы действительно выполняете фиксацию внутри своего теста, тогда все ставки отменены!

Дополнительную информацию можно найти в документации Spring по тестированию интеграции с JDBC.

4
ответ дан 2 December 2019 в 03:48
поделиться

При написании тестов JUnit вы можете переопределить два конкретных методы: setUp () и tearDown (). В setUp () вы можете установить все, что необходимо для тестирования вашего кода, поэтому вам не нужно настраивать что-то в каждом конкретном тестовом примере. tearDown () вызывается после выполнения всех тестовых случаев.

Если возможно, вы можете настроить его так, чтобы вы могли открыть свою базу данных в методе setUp (), а затем очистить ее от тестов и закрыть ее в методе tearDown (). Вот как мы проводили все тесты, когда у нас есть база данных.

Вот пример:

@Override
protected void setUp() throws Exception {
    super.setUp();
    db = new WolfToursDbAdapter(mContext);
    db.open();

    //Set up other required state and data
}

@Override
protected void tearDown() throws Exception {
    super.tearDown();
    db.dropTables();
    db.close();
    db = null;
}

//Methods to run all the tests
4
ответ дан 2 December 2019 в 03:48
поделиться

Предполагая, что у вас есть доступ к базе данных: Другой вариант - создать резервную копию базы данных непосредственно перед тесты и восстановление из этой резервной копии после тестов. Это можно автоматизировать.

2
ответ дан 2 December 2019 в 03:48
поделиться

Если вы используете Spring + Junit 4.x, вам не нужно ничего вставлять в БД. смотреть на Класс AbstractTransactionalJUnit4SpringContextTests .

Также ознакомьтесь с документацией Spring для поддержки JUnit.

1
ответ дан 2 December 2019 в 03:48
поделиться

Я согласен с Brainimus, если вы пытаетесь проверить данные, полученные из базы данных. Если вы хотите протестировать изменения, внесенные в базу данных, другим решением может быть имитация самой базы данных. Существует несколько реализаций баз данных в памяти, которые можно использовать для создания временной базы данных (например, во время JUnit setUp () ), а затем для удаления всей базы данных из памяти (во время tearDown () ). Если вы не используете SQL, зависящий от поставщика, это хороший способ протестировать изменение базы данных, не касаясь реальной производственной базы данных.

Некоторыми хорошими базами данных Java, которые предлагают поддержку памяти, являются Apache Derby , Java DB (но на самом деле это снова вариант Apache Derby от Oracle), HyperSQL (более известный как HSQLDB) и H2 Database Engine . Я лично использовал HSQLDB для создания фиктивных баз данных в памяти для тестирования, и он отлично работал, но я уверен, что другие предложат аналогичные результаты.

1
ответ дан 2 December 2019 в 03:48
поделиться

Это немного драконово, но я обычно стремлюсь стереть базу данных (или только те таблицы, которые мне интересны) перед каждым выполнением метода тестирования. Это, как правило, не работает, поскольку я, конечно, перехожу к большему количеству тестов интеграционного типа.

В случаях, когда у меня нет контроля над базой данных, скажем, я хочу проверить правильное количество строк, созданных после данного вызова, тогда тест будет подсчитывать количество строк до и после проверенного вызова и убедиться, что разница правильная. Другими словами, примите во внимание существующие данные, а затем посмотрите, как тестируемый код изменил ситуацию, не предполагая ничего о существующих данных. Это может потребовать немного усилий для настройки, но позвольте мне протестировать на более «живой» системе.

В вашем случае важны ли конкретные идентификаторы? Не могли бы вы сгенерировать идентификаторы на лету, возможно, случайным образом, убедиться, что они еще не используются, а затем продолжить?

1
ответ дан 2 December 2019 в 03:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: