为什么测试单个 junit 测试有效,而一起测试它们却不行?
与mvn test(或通过ide)一起测试时失败的测试称为EmpiricalTest。
如果我单独测试该文件,它会通过,但否则不会。为什么会这样呢?
您可以从此处。
这就是我在每次测试之前确保数据库为“空白”的方法:
abstract public class PersistenceTest {
@Before
public void setUp() {
db.destroy();
assertIsEmpty(MUser.class);
assertIsEmpty(Meaning.class);
assertIsEmpty(Expression.class);
}
private <Entity> void assertIsEmpty(final Class<Entity> entityClass){
final List<Entity> all = db.getAll(entityClass);
Assert.assertTrue(all.isEmpty());
}
以及失败的测试:
public class EmpiricalTest extends PersistenceTest {
The test that fails when tested together with mvn test (or through the ide) is called EmpiricalTest.
If I test the file alone it goes through, but not otherwise. Why could that be?
You can checkout the Maven source code (to test) from here.
This is how I make sure the database is 'blank' before each test:
abstract public class PersistenceTest {
@Before
public void setUp() {
db.destroy();
assertIsEmpty(MUser.class);
assertIsEmpty(Meaning.class);
assertIsEmpty(Expression.class);
}
private <Entity> void assertIsEmpty(final Class<Entity> entityClass){
final List<Entity> all = db.getAll(entityClass);
Assert.assertTrue(all.isEmpty());
}
and the test that fails:
public class EmpiricalTest extends PersistenceTest {
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这与自动分配的 id 有关。 PU 创建一个 SEQUENCE 表,尽管我从实体中清空了数据库,但实际上并没有删除该表。因此,当我单独测试 EmpiricalTest 时,序列按预期从 1 开始,而当一起测试时,测试会稍后执行,并以更高的意外数字开始。
这导致这个问题。
It got to do with the id automatically assigned. The PU creates a SEQUENCE table, and although I empty the database from my entities, I don't actually drop that table. So when I'm testing EmpiricalTest alone the sequence starts as expected from 1, while when testing together the test is executed later and starts with a higher, unexpected number.
This leads to this question.
这听起来好像测试之间存在依赖关系。据我通过查看您的测试了解到,您正在测试中访问数据存储。是否有可能其中一项测试没有正确清除他的痕迹,从而导致其他测试失败?
针对数据库的测试通常不被视为单元测试,尽管它非常有用。然而,这些类型的测试(您可以将其称为集成测试)的编码更加困难和耗时,因为您必须非常注意您的测试使环境处于它之前发现的确切状态。
This very much sounds as if there are dependencies between the test. As far as I understand from looking at your test, you're accessing the your data storage in the test. Is there a chance that one of the tests doesn't properly cleanup his traces, therefore causing others to fail??
Testing against a DB is usually not considered a unit test, though it is very useful. Those kind of tests (you may call them integration tests) are however more difficult and time consuming to code because you have to pay a lot of attention that your test leaves the environment in the exact state it found it before.
你的问题很常见。在理想的 TDD 世界中,每个测试都应该在与其他测试完美隔离的情况下执行。你违反了隔离,这就是问题所在。
然而,对于测试隔离问题没有简单的解决方案。主要原因是SQL DLL不支持数据库创建/删除,而自动删除表由于可能存在复杂的外键约束而变得复杂。
根据我的经验,最好的想法是在事务内执行测试并在测试结束时回滚数据(就像 Pascal 建议的那样)。 Spring 测试模块 对此提供了很好的支持。
如果您无法在事务边界内执行测试(就像您的事务边界一样),您必须确保每个测试都不会在数据库中留下任何内容(包括外键、约束、序列等),并且测试的设计目的是彼此独立(例如,不依赖于自动生成的 id 值,因为序列生成可以在之前的测试中执行)。
您必须 调试您的 Maven 测试 会话顺序以检查断言有什么问题(我猜您无法判断来自 Surefire 日志)。然后修复测试(失败的测试和在数据库中留下垃圾的另一测试)以相互隔离。
Your problem is very common. In ideal TDD world each test should be executed in the perfect isolation from the other test. You violated the isolation and that's the problem.
However there is no simple solution for the test isolation problem. The main reason is that SQL DLL doesn't support database creation/deletion, while automatically droping tables is complicated due to the possible complex foreign keys constrains.
In my experience the best idea is to execute tests within transaction and rollback data on the end of the test (just like Pascal suggested). Spring test module provides great support for that.
In case you cannot execute test within the transaction boundaries (like yours) you must be sure that each of your test doesn't leave anything in the database (including foreignkeys, constrains, sequences, etc.) and also that tests are designed to be independent of each others (for example don't depend on autogenerated id value because sequence generation could be executed in previous tests).
You must debug your Maven test session order to check out what is wrong with the assertion (I guess that you cannot tell that from the Surefire logs). Then fix the tests (both the failing one and the other one which leaves the rubbish in the DB) to be isolated from each others.