Junit 测试后的数据库清理

2022-09-03 09:04:32

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

编辑:我想强调的是,我正在测试一个服务,它正在写入数据库,我没有直接访问数据库的权限。但是,由于该服务是我们的,因此如果需要,我可以修改该服务以提供任何清理方法。


答案 1

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

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

答案 2

除非您作为测试特定的数据库操作(例如验证是否可以查询或更新数据库),否则您的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);
}

推荐