【问题标题】:Repository inserts don't work in SpringBootTest with WebTestClient存储库插入在带有 WebTestClient 的 SpringBootTest 中不起作用
【发布时间】:2021-11-22 02:37:50
【问题描述】:

我正在通过使端点一次响应一个来将 Spring Boot 应用程序转换为使用 webflux。大多数(Spock)测试运行良好,但我在测试中自动连接 JPA 存储库以插入数据的测试却没有。当资源(我们正在测试的)从中读取时,存储库总是空的。我用不同的存储库进行了数十次这样的测试,它们都有相同的问题。

这是一个测试示例(我们正在测试的资源只是 findById 并从存储库中返回示例):

@SpringBootTest
@AutoConfigureWebTestClient(timeout = "60000")
@Transactional
class PaymentControllerIntegrationTest extends Specification {

    @Autowired
    WebTestClient client

    @Autowired
    PaymentRepository repo

    def "GET /example/{id} returns correct example"() {
        given:
        def needle = new Example(id: 1L)
        def haystack = repo.saveAll([needle, new Example(id: 2L), new Example(id: 3L)])

        when:
        def response = client.get().uri(EXAMPLE_URL, [id: needle.id.toString()]).exchange()

        then:
        response.expectStatus().isOk()
        response.returnResult(ExampleResponse.class).getResponseBody().blockLast().id == needle.id
    }

当我在控制器中设置断点并执行 findAll() 时,存储库始终为空。

  • 我已尝试改用 TestEntityManager.persistAndFlush
  • 我已尝试改用 repo.saveAllAndFlush
  • 我尝试过自动装配 ApplicationContext,然后从中构建 WebTestClient,但我从来没有让自动装配工作

我目前最好的猜测是测试设置不正确(应用程序上下文?)因此测试中的存储库与应用程序中的存储库不同。

【问题讨论】:

  • 您有 2 个事务,1 个未提交(来自测试的那个),而来自控制器的 1 个因此看不到数据(因为它尚未提交)。所以它是同一个存储库但不同的事务。
  • @M.Deinum 但是,当我开始使用 WebTestClient 而不是 MockMvc 时,为什么以及如何改变?
  • 因为现在你正在做一个真正的请求,而不是使用模拟的 MVC。模拟在同一个事务中运行,因为这是对控制器的真实请求,它在单独的线程中运行,因此在事务中运行。使用TestRestTemplate 而不是MockMvc 也是如此。
  • @M.Deinum 如果您添加您的 cmets 作为答案,那么 OP 可以接受它。
  • 是的,请这样做。它确实解决了这个问题(删除@Transactional 并在测试之间删除数据)。

标签: spring spring-data-jpa spock webtestclient


【解决方案1】:

当使用TestWebClient(或TestRestTemplate)时,您实际上是在向您启动的服务器发出一个真正的HTTP 请求。此请求在不同的线程中处理,因此使用新事务。

您的测试也是事务性的,但数据尚未提交,另一个事务只能读取已提交的数据(或者您需要将隔离级别设置为 READ_UNCOMMITTED 但这可能不是您应该或不想做的事情)。

当使用MockMvc 时,您将用模拟实例替换实际容器,它使用MockHttpServletRequest 等。在同一个线程中执行(因此重用同一个事务并且可以看到数据)。

要解决这个问题,请让您的测试不是事务性的,然后清理数据。但是,这会影响测试的性能(因为提交然后删除比在测试后回滚事务要慢)。

【讨论】:

    猜你喜欢
    • 2017-01-30
    • 1970-01-01
    • 2021-05-22
    • 2020-10-02
    • 1970-01-01
    • 2016-04-11
    • 2021-08-17
    • 1970-01-01
    • 2021-12-17
    相关资源
    最近更新 更多