我正在为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));
}
}
答案 0 :(得分:1)
根据文件:
如果您的测试是@Transactional,它会回滚该事务 默认情况下每个测试方法的结束。但是,正如使用这种安排 使用RANDOM_PORT或DEFINED_PORT隐式提供真实 servlet环境, HTTP客户端和服务器分开运行 线程,因此,在单独的事务中。任何启动的事务 在这种情况下服务器上不回滚
由于测试事务与HTTP服务器事务是分开的,因此控制器不会看到测试方法中的更改,直到实际提交测试事务为止。相反,您无法回滚对服务器调用所做的更改。
通过为控制器使用的任何服务/存储库提供模拟实现,您将认真地改善生活。或者,您可以使用DBUnit之类的工具来设置和拆除每个测试用例周围的数据库。