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

时间:2018-04-17 12:47:08

标签: java spring spring-boot jpa testing

我正在为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 个答案:

答案 0 :(得分:1)

根据文件:

  

如果您的测试是@Transactional,它会回滚该事务   默认情况下每个测试方法的结束。但是,正如使用这种安排   使用RANDOM_PORT或DEFINED_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之类的工具来设置和拆除每个测试用例周围的数据库。