Как я могу сохранить сущности во время интеграционного теста SpringBootTest

Я пишу интеграционный тест для 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));
  }
}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
1 439
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Согласно документам:

If your test is @Transactional, it rolls back the transaction at the end of each test method by default. However, as using this arrangement with either RANDOM_PORT or DEFINED_PORT implicitly provides a real servlet environment, the HTTP client and server run in separate threads and, thus, in separate transactions. Any transaction initiated on the server does not roll back in this case

(источник: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications)

Поскольку тестовая транзакция отделена от транзакции HTTP-сервера, контроллер не увидит изменений, внесенных в тестовом методе, пока тестовая транзакция не будет фактически зафиксирована. И наоборот, вы не сможете откатить изменения, внесенные в результате вызова сервера.

Вы серьезно упростите себе жизнь, предоставив имитацию реализации для любого сервиса / репозитория, который использует ваш контроллер. В качестве альтернативы вы можете использовать такой инструмент, как DBUnit, для настройки и удаления базы данных для каждого тестового примера.

Спасибо, в итоге я изменил способ тестирования

JackMahoney 13.06.2018 23:37

Другие вопросы по теме