【发布时间】:2019-03-04 09:41:15
【问题描述】:
我编写了需要事务的测试,它看起来像:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ExchangeApp.class)
@EnableTransactionManagement(proxyTargetClass = true, mode = AdviceMode.PROXY)
@ActiveProfiles({JHipsterConstants.SPRING_PROFILE_TEST})
public abstract class AbstractServiceTest {
所以当我运行单一测试方法时:mvn test -Dtest=TestClassName#method1
按预期工作,但是
mvn test -Dtest=TestClassName
失败,有奇怪的异常,异常表示 @OneToMany 中的约束违反以及 BigDecimal 中除法期间的小数计算异常。在 IDE 中运行时出现相同的异常。 看起来交易管理错过了。有什么想法吗?
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["FK_OPEN_EXEC_ID: PUBLIC.ORDER_PAIR_OPEN_EXEC FOREIGN KEY(EXECUTIONS_ID) REFERENCES PUBLIC.ORDER_PAIR_OPEN(ID) (2)"; SQL statement:
delete from order_pair_open where id=? [23503-197]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
UPD:我也试过了
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<!-- Force alphabetical order to have a reproducible build -->
<runOrder>alphabetical</runOrder>
<parallel>classes</parallel>
<threadCountClasses>1</threadCountClasses>
<threadCountMethods>1</threadCountMethods>
<threadCountSuites>1</threadCountSuites>
</configuration>
</plugin>
UPD:这是针对我的情况的。我正在尝试使用内部的@Async 方法测试服务,所以看来我必须在测试方法名称上标记@Transactional,以便启用事务支持,这就是为什么我尝试使用@EnableTransactionManagement(proxyTargetClass = true, mode = AdviceMode.PROXY) 来启用课堂期间的事务管理测试。这是伪代码:
class Service1Test extends AbstractServiceTest {
Service1 service1;
Repo1 repo1;
//Does not works with class call, but works with method call
//when I mark this method with @Transactional, mentioned exceptions are gone,
// but I cant check result since "registerSynchronization" were not called
@Test
public void test1() throws InterruptedException {
service1.method1();
synchronized (this) {
wait(2000l);
}
assertThat( repo1.findAll().size()).isEqualTo(1);
//repoN check
}
}
@Service
@Transactional
class Service1 {
Service2 service2;
@Async
public void method1() {
//DB operations...
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
service2.method2();
}
});
}
}
@Service
class Service2 {
Repo1 repo1;
public void method2() {
repo1.save(new Entity1());
}
}
@Service
class Service3 {
@Autowired
private ScheduledExecutorService scheduler;
public void method3() {
scheduler.schedule(() -> {
//other transactional services call
}, 1l, TimeUnit.SECONDS);
}
}
@Repository
interface Repo1 extends JpaRepository<Entity1, Long> {
}
@Entity
class Entity1{
}
【问题讨论】:
-
您是否测试过 JHipster 生成的集成测试谎言
AccountResourceIntTest,它们是事务性的,所以使用@Transactional而不是@EnableTransactionManagement,我不明白您为什么需要它。跨度> -
更新:我没有在方法名称上使用事务,但我正在尝试测试使用事务的服务。当我将 Transactional 放在方法名称上时,异常消失了,但不幸的是,我无法检查数据,因为它尚未提交。我测试的方式不对吗? ;)
-
谢谢盖尔。请检查上面的伪代码。
-
同时使用事务和异步很难,因为事务没有传播。通常异步测试的价值很小,因为您要测试的是同步运行时应该相同的业务逻辑。你知道你对这次测试的期望,很抱歉我帮不了你。
标签: spring-boot junit jhipster spring-transactions maven-surefire-plugin