需要解释在使用 Spring 进行测试时预先刷新以避免误报的必要性吗?
在 spring 文档中测试,它指出:
测试 ORM 时避免误报 代码
当您测试涉及以下内容的代码时 ORM 框架,例如 JPA 或 休眠,刷新底层 测试方法中的会话 更新会话的状态。 无法刷新 ORM 框架 底层会话可能会产生错误 积极的一面:你的测试可能会通过,但是 相同的代码在 a 中抛出异常 生活、生产环境。在 以下基于 Hibernate 的示例测试 情况下,一种方法显示错误 正法和另一种方法 正确暴露结果 刷新会话。
有人可以解释为什么我需要打电话冲洗吗?
In the spring documentation regarding testing, it states:
Avoid false positives when testing ORM
codeWhen you test code involving an
ORM framework such as JPA or
Hibernate, flush the underlying
session within test methods which
update the state of the session.
Failing to flush the ORM framework's
underlying session can produce false
positives: your test may pass, but the
same code throws an exception in a
live, production environment. In the
following Hibernate-based example test
case, one method demonstrates a false
positive and the other method
correctly exposes the results of
flushing the session.
Can someone explain why i need to call flush?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好吧,您实际上跳过了有趣的部分,即示例:) 这里是:
这个示例试图说明的是,除非您实际上
刷新
会话(也称为一级缓存)以同步内存中如果数据库发生变化,您并没有真正测试数据库集成,并且可能不会测试真正的预期行为或错过问题。例如,数据库可能会因为违反约束条件而返回错误,如果您不访问数据库,则不会表现出正确的行为,如
falsePositive()
测试中所示方法同上。此测试方法应该会失败,或者预期会出现异常但会通过。另一方面,另一种带有刷新的测试方法确实测试了真实的行为。因此需要flush
。Well, you actually skipped the interesting part, the example :) Here it is:
What this example tries to illustrate is that unless you actually
flush
the session (A.K.A. the first level cache) to sync in-memory changes with the database, you're not really testing the database integration and might not test the real expected behavior or miss a problem.For example, the database could return an error because of, say a constraint violation, and if you don't hit the database, you won't exhibit this right behavior, as in the
falsePositive()
test method above. This test method should fail, or expect an exception but will just pass. On the other hand, the other test method with the flush does test the real behavior. Hence the need toflush
.使用 @Transactional 注释 Spring 测试很方便,但这不是生产代码的执行方式。 @Transactional 注释将在运行测试方法之前启动事务,并在测试方法完成时回滚它。
虽然提交之前有刷新,但回滚则不然,因此手动刷新是一种安全机制,可确保所有实体更改都转换为 SQL 语句。
更合适的设计是像这样明确地绘制事务边界:
TransactionTemplate 将提交您的代码,因此无需手动刷新。
如果您通过 @Transactional 服务方法的接口调用 @Transactional 服务方法,则根本不需要 transactionTemplate,因为您正在调用 Spring 代理,它将调用 TransactionInterceptor (假设您指示 Spring 了解事务注释:),因此事务将被代表您开始/承诺。
Annotating Spring tests with @Transactional is convenient but it's not how your production code will be executed. The @Transactional annotation will start a transaction prior to running your test method and it will roll it back when the test method finishes.
While commit is preceded by a flush, the roll-back is not, so a manual flush is a safety-mechanism to ensure all Entity changes are translated to SQL statements.
A more appropriate design would be to draw the transaction boundaries explicitly like this:
The TransactionTemplate will commit your code so there's no need for manual flushes.
If you call @Transactional service methods through their interface, you won't need the transactionTemplate at all, since you are calling a Spring proxy which will call TransactionInterceptor (assuming you instructed Spring to be aware of transaction annotations: ) and therefore transactions will be started/committed on your behalf.
Spring 文档使用了错误的概念。已经明确了
这里是维基百科
如果您看到Spring提供的示例,生产环境会抛出异常(A GenericJDBCException) ,但尚未检测到。为了查看,您必须在使用某些 ORM 提供程序时调用底层提交。
XUnit 测试模式定义
所以正确的概念是 falseNegative
Spring documentation uses the wrong concept. It has been clear
Here goes wikipedia
If you see the sample provided by Spring, The production environment throws an exception (A GenericJDBCException), but it has not been detected. In order to see, you must call the underlying commit when using some ORM provider.
XUnit Test patterns definition
So the right concept is falseNegative
有人检查过@TransactionConfiguration 注释吗?如果您在项目中使用 @Transactional 注解驱动,则只需在测试用例中设置 @TransactionConfiguration(defaultRollback = false, transactionManager = "YourTransactionManager") 即可完美运行,希望这会对您有所帮助。
Does anyone checked with the annotation @TransactionConfiguration? If you are using @Transactional annotation driven in your project, you can simply set @TransactionConfiguration(defaultRollback = false, transactionManager = "YourTransactionManager") in your test case will work perfectly, hopefully this will helps you.