如何在@Transactional SpringBootTest测试用例中测试spring批处理作业?

问题描述 投票:0回答:1

我今天似乎赢不了...

  1. 是否有一种方法可以在Spock SpringBootTest集成测试中从OneToMany关系中读取,而无需将测试注释为@Transactional或添加不切实际的spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
  2. OR,有没有办法从@Transactional测试用例中启动Spring-Batch Job?

让我详细说明...

我正在尝试为Spring Batch报表过程提供一个简单的Spring Boot Integration测试,该测试从错综复杂的DB2表Web读取并为感兴趣的系统生成一系列更改消息。我正在使用Groovy Spock测试框架和一个H2内存数据库,其中填充了我的DB2表数据的代表性片段。

在测试开始时,我试图使用给定表中的每个实体在驱动我的消息传递的变更跟踪表中生成条目。

setup:
List allExistingTestPeople = peopleRepository.findAll()
Collections.shuffle(allExistingTestPeople)
allExistingTestPeople?.each { Person person ->
    Nickname nicknames = person.nicknames
    nicknames?.each { Nickname nickname ->
        changeTrackingRepository.save(new Change(personId: person.id, nicknameId: nickname.id, status: NEW))
    }
}

将这些作为我的DB2域类:

@Entity
@Table(name = "T_PERSON")
public class Person {

    @Id
    @Column(name = "P_ID")
    private Integer id;

    @Column(name = "P_NME")
    private String name;

    @OneToMany(targetEntity = Nickname.class, mappedBy = "person")
    private List<Nickname> nicknames;
}

@Entity
@Table(name = "T_NICKNAME")
public class Nickname{

    @EmbeddedId
    private PersonNicknamePK id;

    @Column(name = "N_NME")
    private String nickname;

    @ManyToOne(optional = false, targetEntity = Person.class)
    @JoinColumn(name = "P_ID", referencedColumnName="P_ID", insertable = false, updatable = false)
    private Person person;
}

@Embeddable
public class PersonNicknamePK implements Serializable {

    @Column(name="P_ID")
    private int personId;

    @Column(name="N_ID")
    private short nicknameId;
}

但是,尽管我正在测试用例的上下文中从OneToMany关系中读取,但我正在得到这个LazyInitializationException ...

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.my.package.db2.model.Person.nicknames, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:602)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:217)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:161)
at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:350)

我在网上遇到建议,用@Transactional批注注释我的测试用例,这肯定使我更进一步,使我可以阅读这种OneToMany关系。但是,当我随后尝试启动Spring Batch Job时,我想从我的when子句中进行测试:

@Transactional
def "Happy path test to validate I can generate a report of changes"() {
    setup:
    //... See above

    when:
    service.launchBatchJob()

    then:
    //... Messages are generated
} 

我遇到一个例外,即无法从事务上下文中启动Spring Batch作业!即使我通过ResourcelessTransactionManagerMapJobRepositoryFactoryBean使用内存中的作业管理器,由于这只是我正在编写的短期计划脚本,因此...

java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove @Transactional annotations from client).
    at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:177)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy125.createJobExecution(Unknown Source)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:134)
    at com.my.package.service.MyService.launchBatchJob(MyService.java:30)

到目前为止,似乎唯一有效的方法是,如果我删除@Transactional批注,而是将spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true添加到我的application-test.properties文件中。但是,这似乎不是一个好主意,因为它不现实-如果我添加它,那么即使由于延迟初始化例外而在我的代码中存在错误,我也不会在测试中看到它。

对不起,这本小说,希望有人能指出我正确的方向:(

java spring-data spring-batch spock lazy-initialization
1个回答
0
投票

发生此错误是因为您的代码已经在Spring Batch驱动的事务中执行。因此,在事务范围内运行作业是不正确的。但是,如果仍然要禁用作业存储库完成的事务验证,则可以将validateTransactionState设置为false,请参见AbstractJobRepositoryFactoryBean#setValidateTransactionState

© www.soinside.com 2019 - 2024. All rights reserved.