如何在Spring中单独运行每个集成测试,或者至少在每次测试之前运行所有命令行管理器?

时间:2018-04-24 10:39:59

标签: java spring spring-boot spring-test

我有一个Spring Boot应用程序,我正在使用spring-boot-starter-test。

我有一堆集成测试,使用REST调用将数据插入应用程序。我用@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

运行这些

每次测试后,我都会在数据库中找到一些数据。我希望每个测试都是真正独立的,但我还没有找到一种方法。我尝试在每个测试中放置@Rollback,但由于我通过REST调用从外部插入数据,这可以理解为不起作用。

所以以前我只是通过在运行测试后为每个实体执行删除查询(即类似Query deleteProjects = entityManager.createQuery("DELETE FROM Project"); deleteProjects.executeUpdate();)来删除测试之间的所有数据,而是以相当低级的方式删除。

但是,我最近添加了一个将在CommandLineRunner中创建的管理员用户帐户。我发现这个CommandLineRunner也只为所有测试组合运行一次,所以在第一次测试完成并删除所有数据后,我将失去管理员角色。

设置它的好方法是什么?我意识到启动整个应用程序需要一些时间,所以一个完整的新启动不会是理想的。在每次测试之前告诉Spring运行CommandLineRunner的一些方法会很好。我不想自己实例化和运行它,这将非常hacky,我不确定这在交易方面如何工作。我可以排除此管理员用户帐户在查询中被删除,但之后我仍在浏览系统。

1 个答案:

答案 0 :(得分:1)

目前,您需要拥有此管理员帐户以及此管理员帐户的Spring上下文存在鸡和蛋问题。我发现这样做的一个好方法是拥有一个Spring配置文件@Profile("test")并将其放在一些Component上,这会创建您需要的管理员帐户:

@Component
@Profile("test")
public class CreateAdminBean {
    @Autowired
    UserRepo repo;

    public CreateAdminBean() {
        // TODO your job but something like:
        User admin = new User();
        admin.setAdmin(true);
        repo.create(admin);
    }
}

如果您希望测试真正独立于彼此,则需要每次都重新创建上下文,并确保每次都擦除数据库。这将花费你一些时间和IMO是不必要的,但如果你有你的理由,你有你的理由。我个人会嘲笑所有的服务。

你可以拥有你的数据库JPA Hibernate spring.jpa.hibernate.ddl-auto= create-drop。我通常不会这样做,只是有一个方法可以清除所有表并在每次测试后运行,但这不是你在问题中提出的问题,我希望你的测试中会看到@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)代码。