Java 如何在Springboot集成测试中获取JPA上下文?

Java 如何在Springboot集成测试中获取JPA上下文?,java,spring-boot,jpa,cucumber,Java,Spring Boot,Jpa,Cucumber,我正在用jpa运行Springboot应用程序。我正在尝试建立一个基于Cucumber的集成测试。在我的测试中,当我尝试访问repo时,我会得到一个“org.hibernate.LazyInitializationException”(带有一条消息“No Session”。)。这只发生在我的集成测试中,而不是在实际的应用程序中。一种解决方法是将@Transactional放在执行调用的方法上,但如果我在新线程中执行,这将不起作用 我的第一个问题是:为什么没有@Transactional注释它就不

我正在用jpa运行Springboot应用程序。我正在尝试建立一个基于Cucumber的集成测试。在我的测试中,当我尝试访问repo时,我会得到一个“org.hibernate.LazyInitializationException”(带有一条消息“No Session”。)。这只发生在我的集成测试中,而不是在实际的应用程序中。一种解决方法是将@Transactional放在执行调用的方法上,但如果我在新线程中执行,这将不起作用

我的第一个问题是:为什么没有@Transactional注释它就不能工作? 我的第二个问题是:为什么它不能在新线程中使用@Transactional注释

以下是我的代码的简化版本:

黄瓜试验:

@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources/some-integration-test.feature")
public class IntegrationTests {}
步骤如下:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class IntegrationSteps {

    @Autowired
    SomeRepo repo;

    @When("two updates happen at the same time")
    public void twoUpdatesHappenAtTheSameTime() {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        executorService.execute(set("Thread 1"));

        executorService.execute(set("Thread 2"));

        executorService.shutdown();
        executorService.awaitTermination(1, TimeUnit.MINUTES);
    }

    public void set(String someThing) {
        Some some = repo.getOne(1234);
        repo.setSomeThing(someThing);
        repo.save(some);
    }
}
回购协议:

@Repository
public interface SomeRepo extends JpaRepository<Some, Integer> {}
@存储库
公共接口SomeRepo扩展了JpaRepository{}

问题似乎出在
getOne()
上。使用
getOne()
只能获得对实体的引用。在尝试访问实体的字段之前,不会执行对数据库的真正调用。 通常,当使用
getOne()
时,这些字段是惰性加载的,但由于某种原因(我仍然不清楚),这在SpringBootTest中不起作用

我找到了两种解决此问题的方法:

  • @Transactional
    注释测试。这样,您将有一个上下文来加载实体。缺点是,您似乎仍然无法获得实体的最新版本。在我的例子中,我更新了代码中的实体,而在测试代码中,实体中不存在更新(即使更新发生在
    getOne()
    调用之前)
  • 不要使用
    getOne()
    ,而是使用
    findById()
    。缺点是,
    findById()
    被急切地加载,但由于我们只在测试中使用它,它不会影响应用程序的性能