使用断言的一个明显问题

单元测试是任何足够大的项目的重要组成部分。 我想与您分享一个有关他们非显而易见的大规模坠落的小侦探故事。

首先,由于一定程度的无害提交,该项目中大约进行了150个测试,而下降测试集却不稳定。 测试未互连,测试按顺序进行。 内存中的h2数据库用作测试的数据源。 在这150个测试中,绝大多数的失败都伴随着日志中的错误:“无法获得连接,池错误超时等待空闲对象”。 应该说在项目中执行测试时连接池的大小为1。

一小段抒情题:在项目代码中,交易会定期与流程断开连接,然后在单独的交易中执行代码,最后,交易被反向链接。 在这种情况下,将编写一个帮助程序类,其用法如下所示:

TransactionRunner.run(dbDataManager(), new MethodTransaction() { @Override public ExecutionResult runInTransaction() throws Exception { // ,       return result; } ); 

分析的结果表明,在包含事务中代码调用的失败测试之后,该错误开始出现:

 TransactionRunner.run(dbDataManager(), new MethodTransaction() { @Override public ExecutionResult runInTransaction() throws Exception { // ...   // assert   assert( 1, result.getSomeNotEqualOneIntValue() ); return result; } ); 

看一下TransactionRunner类内部,方法调用将导致以下代码:

 protected ExecutionResult run() throws CommonException { Transaction outerTr = getThreadTransaction(); bindThreadTransaction(null); try { beginTransaction(); try { setResult(transactionCode.runInTransaction()); } catch (Exception e) { dbDataManager().rollbackTransaction(); if (transaction.onException(this, e)) throw e; } dbDataManager().commitTransaction(); return getResult(); } catch (Exception e) { throw ExceptionUtil.createCommonException(e); } finally { bindThreadTransaction(outerTr); } } 

那么这是什么问题呢? 问题在于,由于执行测试代码而产生的AssertionError不能从Exception继承,这意味着嵌套的事务既不回滚也不提交。 由于连接池的大小等于1,因此在尝试通过后续测试获取连接对象时,会收到相同的错误“无法获取连接,池错误超时等待空闲对象”。

道德:必须谨慎地将断言放在测试中,在非显而易见的情况下,尤其是在大规模崩溃的情况下,解决方案之一是检查异常处理是否将未继承自Exception的对象考虑在内。

在我看来,这个案子值得解决,也许这种经历对某人有用。

Source: https://habr.com/ru/post/zh-CN420509/


All Articles