存储库插入在带有 WebTestClient 的 SpringBootTest 中不起作用
Repository inserts don't work in SpringBootTest with WebTestClient
我正在将 spring 引导应用程序转换为使用 webflux,方法是让端点一次一个地响应。大多数 (Spock) 测试工作正常,但我在测试中自动连接 JPA 存储库以插入数据的那些测试没有。当资源(我们正在测试的)从中读取时,存储库始终为空。我对不同的存储库进行了数十次这样的测试,它们都有相同的问题。
这是一个测试示例(我们正在测试的资源只执行 findById,returns 来自存储库的示例):
@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,但我从未让自动装配工作
我目前最好的猜测是测试设置不正确(应用程序上下文?)所以测试中的存储库与应用程序中的存储库不同。
当使用 TestWebClient
(或 TestRestTemplate
)时,您实际上是在向启动的服务器发出真正的 HTTP 请求。此请求在不同线程中处理,因此使用新事务。
您的测试也是事务性的,但数据尚未提交,另一个事务只能读取已提交的数据(或者您需要将隔离级别设置为 READ_UNCOMMITTED
但这可能不是您应该做的或者想做)。
当使用 MockMvc
时,您正在用模拟实例替换实际容器,它使用 MockHttpServletRequest
等。 和 在同一个线程中执行(从而重复使用相同的事务并可以看到数据)。
要解决这个问题,请让您的测试不是事务性的,然后清理数据。但是,这会影响测试的性能(因为提交然后删除会随着测试后回滚事务而变慢)。
我正在将 spring 引导应用程序转换为使用 webflux,方法是让端点一次一个地响应。大多数 (Spock) 测试工作正常,但我在测试中自动连接 JPA 存储库以插入数据的那些测试没有。当资源(我们正在测试的)从中读取时,存储库始终为空。我对不同的存储库进行了数十次这样的测试,它们都有相同的问题。
这是一个测试示例(我们正在测试的资源只执行 findById,returns 来自存储库的示例):
@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,但我从未让自动装配工作
我目前最好的猜测是测试设置不正确(应用程序上下文?)所以测试中的存储库与应用程序中的存储库不同。
当使用 TestWebClient
(或 TestRestTemplate
)时,您实际上是在向启动的服务器发出真正的 HTTP 请求。此请求在不同线程中处理,因此使用新事务。
您的测试也是事务性的,但数据尚未提交,另一个事务只能读取已提交的数据(或者您需要将隔离级别设置为 READ_UNCOMMITTED
但这可能不是您应该做的或者想做)。
当使用 MockMvc
时,您正在用模拟实例替换实际容器,它使用 MockHttpServletRequest
等。 和 在同一个线程中执行(从而重复使用相同的事务并可以看到数据)。
要解决这个问题,请让您的测试不是事务性的,然后清理数据。但是,这会影响测试的性能(因为提交然后删除会随着测试后回滚事务而变慢)。