我正在尝试为我的 Tomcat 应用程序实现集成测试,但我的问题是应用程序与测试分开启动,因此测试无法访问应用程序上下文,也无法访问数据库。
我的想法是在正在运行的应用程序“内”运行测试,这样我就可以@Autowire EntityManager 并在测试期间检查数据库的状态,甚至创建用于测试的数据库实体。
我这样做的唯一想法是通过测试以编程方式实际运行应用程序作为 ClassPathXmlApplicationContext("applicationContext.xml")
并访问上下文。这会工作,但调试起来会非常困难,因为我们无法在测试期间使用热交换。另外我猜服务器会在测试结束后立即停止。我想这不是最佳和正确的解决方案。
编辑:
我的问题可能不清楚,所以我会尽力澄清。
我有一个带有 Spring 和 Hibernate 的 Tomcat 应用程序。 Spring bean 和 Hibernate 数据库连接在 Tomcat 应用程序启动时初始化。问题是如何从单独启动的 src/test/java
中用 @Test
注释的方法运行 Activity Spring bean 的测试。
考虑这个类:
@Component
class MyRepository {
@Autowired
EntityManager em;
@Transactional
public void myMethod(MyEntity entity) {
// do some job with entity
...
em.flush();
}
}
这个类将被 Tomcat 初始化为一个 MyRepository
bean。
为了测试它,我不能只调用 new MyRepository().myMethod(...)
- 我需要访问 bean。问题是从 @Test
方法访问 bean:
@Test
void testMyRepository() {
Item item = ...
// then use the repository to handle the entity
context.getBean(MyRepository.class).myMethod(item);
// then assert the state of the database
context.getBean(EntityManager.class).find(Item.class, ...) ...
}
我可能可以在测试的初始化中得到 context
ApplicationContext context = ClassPathXmlApplicationContext("applicationContext.xml");
但这意味着每次测试开始时都要启动整个应用程序。更好的解决方案是应用程序可以独立于测试运行。
希望我的问题现在更清楚了。
最佳答案
我建议您使用 SpringRunner 启动 Spring 应用程序上下文并在该运行实例上执行测试。您可以自定义上下文,使其不包含您不想测试的部分,并且可以为需要一些外部资源(REST 客户端等)的组件创建模拟。看看 Spring docs或 Spring Boot docs .
如果多个测试使用相同的 Spring 上下文配置,则上下文只启动一次并重复使用。因此,最好在测试的父类中进行配置。您可以将任何 Spring bean Autowiring 到您的测试中并对其进行测试。
您可以使用内存数据库(例如 H2 )而不是生产数据库,因此您的测试不依赖于外部基础设施。要初始化数据库,请使用 Flyway 等工具或 Liquibase .要在每次测试前清除数据库,您可以使用 @Sql注释。
您可以找到许多具有此类测试的项目示例,例如我自己的 demo .
如果你想测试一个外部系统,我会建议像 JMeter 这样的东西.
关于java - Spring应用的集成测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48446812/