Junit测试后的数据库清理

Ash*_*ish 12 java database junit unit-testing

我必须使用Junit测试一些Thrift服务.当我将测试作为Thrift客户端运行时,服务会修改服务器数据库.我无法找到一个好的解决方案,可以在每次测试运行后清理数据库.清理很重要,特别是因为ID必须是唯一的,目前从XML文件中读取.现在,我必须在运行测试后手动更改ID,以便下一组测试可以运行而不会在数据库中抛出主键冲突.如果我可以在每次测试运行后清理数据库,那么问题就完全解决了,否则我将不得不考虑其他解决方案,比如生成随机ID并在需要ID的地方使用它们.

编辑:我想强调一下,我正在测试一个写入数据库的服务,我没有直接访问数据库.但是,因为服务是我们的,我可以修改服务,以便在需要时提供任何清理方法.

小智 14

如果您使用的是Spring,那么您需要的只是测试类上的@DirtiesContext注释.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-context.xml")
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class MyServiceTest {
   ....
}
Run Code Online (Sandbox Code Playgroud)

  • DirtiesContext是关于Spring上下文的重新创建 - 这是耗时的操作,所以它不是好方法 (2认同)
  • 对于任何实际项目来说这都不是一个好的解决方案。它将为每个测试启动 spring boot 应用程序。经过几次测试课程后,需要几分钟才能完成,并且会大大减慢开发速度。您希望测试快速,以便可以尽可能频繁地运行它们,以避免破坏代码。 (2认同)

bra*_*mus 7

Unless you as testing specific database actions (verifying you can query or update the database for example) your JUnits shouldn't be writing to a real database. Instead you should mock the database classes. This way you don't actually have to connect and modify the database and therefor no cleanup is needed.

您可以通过几种不同的方式模拟您的课程.您可以使用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);
}
Run Code Online (Sandbox Code Playgroud)

  • "除非您测试特定的数据库操作(例如,验证您可以查询或更新数据库),否则您的JUnits不应该写入真正的数据库."对此没有普遍的协议.在一个阵营中,我们有那些认为数据库应该被嘲笑的人,而另一方面我们有那些认为应该对真实数据库执行所有数据库测试的人,最好是与生产数据库相匹配的数据库. (26认同)

nin*_*ded 5

如何使用像DBUnit这样的东西