代码之家  ›  专栏  ›  技术社区  ›  JackMahoney

如何在SpringBootTest集成测试期间持久化实体

  •  0
  • JackMahoney  · 技术社区  · 7 年前

    我正在为SpringBoot 2 RestController编写一个集成测试。我想测试404行为和实体的创建。然而,当我尝试在测试之前或期间创建实体并持久化它们时,它们不会持久化到SpringBoot上下文中。我的意思是,它们在测试上下文中是可见的(在测试调试期间),但对控制器来说是不可见的(即它找不到它们,我的测试失败)。我做错了什么?

    如何在测试期间持久化实体并刷新上下文,以便在集成测试期间调用的代码能够看到它们?我不想使用@before注释来填充数据库,因为我想在@test方法中这样做。

    这是我的密码。谢谢

    @RunWith(SpringRunner.class)
    @Transactional
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class InvoiceControlllerIT extends GenericControllerIT {
    
      @Autowired
      EntityManager entityManager;
    
      @Test
      @Transactional
      public void cascadesChildEntityAssociationOnCreate() throws IOException {
        assertThat(invoicerRepository.count(), equalTo(0L));
        assertThat(invoiceRepository.count(), equalTo(0L));
        assertThat(invoiceeRepository.count(), equalTo(0L));
        // create an invoicee
        Invoicee savedInvoicee = invoiceeRepository.save(new Invoicee());
        assertThat(invoiceeRepository.count(), equalTo(1L));
        // create an invoicer
        Invoicer savedInvoicer = invoicerRepository.save(new Invoicer());
        assertThat(invoicerRepository.count(), equalTo(1L));
        // THIS IS THE PROBLEM, FLUSHING DURING THE TEST DOES NOT EFFECT THE CONTROLLERS ABILITY TO SEE THE NEWLY CREATED ENTITIES
        entityManager.flush();
        // create input
        InvoiceInputDto inputDto = InvoiceInputDto
                .builder()
                .invoicee(savedInvoicee.getId())
                .invoicer(savedInvoicer.getId())
                .name("test-name")
                .build();
        // make call
        ResponseEntity<InvoiceDto> response = template.postForEntity(url("/invoices", TOKEN), inputDto, InvoiceDto.class);
        assertThat(response.getStatusCode(), equalTo(HttpStatus.CREATED));
        assertThat(response.getBody().getName(), equalTo(inputDto.getName()));
        // check associations
        assertThat(invoiceeRepository.findById(savedInvoicee.getId()).get().getInvoices(), hasSize(1));
      }
    }
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   crizzis    7 年前

    根据文件:

    如果您的测试是@事务性的,它将在 默认情况下,每个测试方法结束。然而,使用这种安排 使用RANDOM\u PORT或DEFINED\u PORT隐式提供 servlet环境, HTTP客户端和服务器分别运行 线程,因此,在单独的事务中。 任何已启动的事务 在这种情况下,不会在服务器上回滚

    (来源: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications )

    由于测试事务与HTTP服务器事务是分开的,所以在测试事务实际提交之前,控制器不会看到测试方法中所做的更改。相反,您将无法回滚由于服务器调用而进行的更改。

    通过为控制器使用的任何服务/存储库提供模拟实现,您的生活将变得更加轻松。或者,您可以使用DBUnit之类的工具来设置和分解每个测试用例周围的数据库。