【问题标题】:JUnit-Test differs between class and project testingJUnit-Test 在类测试和项目测试之间有所不同
【发布时间】:2012-09-15 22:14:24
【问题描述】:

我在我的 Java 应用程序中遇到了一个与单元测试相关的奇怪错误。

在单元测试期间,我使用预先填充了自定义数据的内存 HSQLDB(通过自动触发的插入脚本)和 Hibernate 作为 ORM 来访问它。

问题如下,如果我在单个类(即:TestDummyClass.java)上开始单元测试,则在每个方法测试之后重新创建数据库(从原始插入脚本)。。 p>

如果我在包含多个测试类的整个项目 (src/test) 上启动单元测试,则数据库会在每个测试类的开头初始化,而不是在每个测试方法上初始化。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:com/wizche/app-context-test.xml" })
public class TestDummyClass {
.....
}

这意味着,例如,如果在 TestDummyClass 中我在某些测试方法中更改了数据库(即创建一个新对象),那么新对象将留在那里以用于同一类中的以下测试方法。因此,如果我在项目或单个类上启动它,断言应该会有所不同!

谁能解释一下为什么会这样?我如何决定何时恢复 clean-db?

注意:我正在使用 SpringJUnit4ClassRunner 和整个测试项目的自定义上下文配置(其中没有与单元测试相关的参数)。 NB2:我直接在 SpringEclipse 中启动 JUnit

【问题讨论】:

  • 能否提供测试类的配置(注解)?你使用@DirtiesContext 吗?我想这是你需要关注的方向。
  • 不,我刚刚更新了帖子

标签: java spring hibernate junit hsqldb


【解决方案1】:

原因是,如果您使用 SpringJUnit4ClassRunner,如果您对多个测试使用完全相同的位置,它往往会缓存应用程序上下文 - 这种缓存是跨套件的,因此如果您在单个套件中执行项目中的所有测试, 并在多个测试中使用相同的应用程序上下文位置,您很可能会获得一个缓存的上下文 - 如果您在上下文中修改 bean,这也将反映在其他测试中。

解决方法是在测试类或测试方法中添加@DirtiesContext 注解

【讨论】:

  • 如果我添加 @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) 它会在两种运行类型(单个类/项目)的每个测试方法之后重新生成数据库。但我的目标是,对于两个测试,数据库都会在每个类的开始时重新生成。可能吗?我的问题的真正解决方案是在我所有的 120 个测试类上添加 DirtiesContext? (对我来说似乎是一种解决方法)
  • 不一定适用于所有测试 - 如果您的测试修改了上下文,那么您需要添加 @DirtiesContext,以指示 Spring 将其从缓存中删除。此外,如果您只是使用不同的上下文文件,将为不同的上下文创建一个新的缓存条目。不过我可能误解了你的评论。
  • 唯一剩下的问号是为什么如果我在一个类上启动单个 UT,它会在每个测试方法之后不断重新生成一个 DB(不管我是否声明了 @DirtiesContext(classMode = ClassMode.AFTER_CLASS) 或我完全删除了@DirtiesContext 注释)。两者的期望行为是仅在 setUp() 期间生成一次 DB。
  • 是的,通读@DirtiesContext javadoc,它应该在整个测试类 classMode=AFTER_CLASS 之后将上下文标记为脏,如果它不能以这种方式工作,则可能是一个错误你。
【解决方案2】:

Eclipse 在单个 JVM 中运行单元测试,因此理论上即使在单个类上运行,您也应该看到与从 src/test 运行相同的行为。我在想运行你所有的测试你更有可能看到问题。当您进行单个类测试时,是什么让您确保在每个方法之后重新创建数据库 - 只是想确保这是准确的?

在查看此link 之前提出了类似的问题。会有帮助的。

【讨论】:

  • 感谢您的回复,我很确定这一点,因为我使用我的 DAO 检查 db 中的项目,这意味着如果我启动测试类,对 myDao.getAll() 的调用会返回不同的值(较低的值)单独或在项目中(较大的值,因为在我正在检查的测试方法之前创建的对象)。
  • 除了在每次测试后回滚事务外,我没有看到任何其他选项。不确定您使用的是哪个版本的 Spring,但请尝试查看 @Transactional@TestExecutionListeners 上的 spring 文档,这将有所帮助。我相信@DirtiesContext(正如其他人指出的那样)可能会通过提供所需的测试执行侦听器来提供帮助,但您必须使用@Transactional 注释类。
  • 实际上使用 @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) 我可以强制单个/项目 UT 在每种方法之后重新生成数据库。我的目标是仅在 setUp() 时间生成数据库,目前当我启动单个类 UT 时,它会在每个测试方法之后不断重新生成数据库,与我设置的 DirtiesContext(AFTER_CLASS 或无)无关,在某些情况下单类测试的行为方式不同。
【解决方案3】:

我建议使用DBUnit 来协助构建和拆除您的数据库。它提供了动态执行此操作的方法,并与所有主要的数据库提供程序进行交互。

【讨论】:

    猜你喜欢
    • 2010-11-14
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    相关资源
    最近更新 更多