В настоящее время я пытаюсь реализовать @Transactional в моем весеннем загрузочном приложении (v2.2.5.RELEASE) в Java 8.
В настоящее время я запускаю тестовый сценарий, в котором недопустимый параметр передается как contactEntryType ». При этом никаких изменений в базе данных не должно произойти, но «ContactInformation» для «Contactable» («Person») создается и сохраняется (без отката).
Я уже добавил @EnableTransactionManagement в аннотированную @Configuration class, а также 'spring.jpa.open-in-view = false', как это было рекомендовано в другом месте.
Указанный метод аннотируется с помощью: @Transactional (распространение = Propagation.REQUIRES_NEW, rollbackFor = ResponseStatusException.class Сначала он вызывает getOrCreateContactInformation (...), а затем getOrCreateEntry (...)
private <T extends Contactable> ContactInformation getOrCreateContactInformation(T contactable) {
if (contactable.getContactInformation() == null) {
ContactInformation contactInformation = new ContactInformation();
contactable.setContactInformation(contactInformation);
}
return contactable.getContactInformation();
}
«contactabe» является управляемым объектом.
private ContactEntry getOrCreateEntry(ContactProjection projection) {
// find existing
ContactEntry entry = contactEntryRepository.findByContactEntryTypeAndEntry(
ContactEntryType.get(projection.getEntryType()), projection.getEntry()
).orElse(null);
// create new if needed
if (entry == null) {
ContactEntryType type = ContactEntryType.get(projection.getEntryType());
type.validate(projection.getEntry());
entry = ContactEntry.builder()
.contactEntryType(type)
.entry(projection.getEntry())
.build();
}
return entry;
}
'ContactEntryType.get ( projection.getEntryType ()) 'генерирует исключение ResponseStatusException в тестовом сценарии, как и должно (я проверял его)
Этот тест выглядит следующим образом.
@Test
@WithMockUser(authorities = {"c_person", "l_person", "c_cont"})
public void createContact_violation_unknownType() throws Exception {
int id = createPersonDataSet().get(0).getId();
ContactProjection.Imp contact = ContactProjection.Imp.builder()
.type("test type")
.entryType("unknown")
.entry("hydrofin@gmail.com")
.build();
assertTrue(contactInformationRepository.findAll().isEmpty());
mockMvc.perform(
post(linkTo(CONTROLLER.createContact(id, null)).toUri())
.contentType(APPLICATION_JSON_UTF8)
.content(asJson(contact))
).andExpect(status().isUnprocessableEntity());
assertTrue(contactRepository.findAll().isEmpty());
assertTrue(contactEntryRepository.findAll().isEmpty());
assertTrue(contactInformationRepository.findAll().isEmpty(), "No ContactInformation got created"); // <--- FAILS
assertNull(personRepository.getOne(id).getContactInformation());
}
Метод на контроллере вызывает @ Транзакционный аннотированный метод из другого класса, и все методы в этой цепочке, кроме показанных приватных ниже аннотации, публикуются * 1 036 *.
Класс теста помечен @Transactional и использует junit5
Мои свойства теста
spring.jpa.database = H2
spring.jpa.show-sql=true
spring.jpa.open-in-view = false
logging.level.org.springframework.transaction.interceptor = TRACE
Тест выводит следующее (это часть этого):
Began transaction (1) for test context [DefaultTestContext@598bd2ba testClass = PersonControllerMvcTest,
...
Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll]
Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findById]
Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findById]
Getting transaction for [xxx.services.ContactService.save]
Completing transaction for [xxx.services.ContactService.save] after exception: org.springframework.web.server.ResponseStatusException: 422 UNPROCESSABLE_ENTITY "Unable to find ContactEntryType 'unknown'"
Applying rules to determine whether transaction should rollback on org.springframework.web.server.ResponseStatusException: 422 UNPROCESSABLE_ENTITY "Unable to find ContactEntryType 'unknown'"
Winning rollback rule is: RollbackRuleAttribute with pattern [org.springframework.web.server.ResponseStatusException]
...
Тем не менее после этого hibernate создает сущности.
Я благодарен за любую помощь, спасибо.
РЕДАКТИРОВАТЬ:
Кажется, проблема связана с аннотацией @Transactional, но как я могу получить эффект @Transactional в тесте, не влияя на реальный код службы и контроллера?