Hibernate Validator не запускается, так как Spring Repository.save () вызывается в модульных тестах - PullRequest
0 голосов
/ 27 июня 2018

Это моя сущность:

@Builder
@Data
@Entity
@Table(name = "audit_log")
public class AuditEventEntity {
    @Id
    @GeneratedValue
    private UUID id;

    private long createdEpoch;

    @NotNull
    @Size(min = 1, max = 128)
    private String label;

    @NotNull
    @Size(min = 1)
    private String description;
}

А это мой репозиторий:

@Repository
public interface AuditEventRepository extends PagingAndSortingRepository<AuditEventEntity, UUID> {
}

Когда я пишу следующий модульный тест для хранилища, сохранение прошло успешно, хотя поле «label» пустое!

@DataJpaTest
@RunWith(SpringRunner.class)
public class AuditRepositoryTest {
    @Test
    public void shouldHaveLabel() {
        AuditEventEntity entity = AuditEventEntity.builder()
                .createdEpoch(Instant.now().toEpochMilli())
                .description(RandomStringUtils.random(1000))
                .build();
        assertThat(entity.getLabel()).isNullOrEmpty();
        AuditEventEntity saved = repository.save(entity);
        // Entity saved and didn't get validated!
        assertThat(saved.getLabel()).isNotNull();
        // The label field is still null, and the entity did persist.
    }

    @Autowired
    private AuditEventRepository repository;
}

Использую ли я @NotNull или @Column(nullable = false), база данных создается с флагом not null в столбце:

Hibernate: create table audit_log (id binary not null, created_epoch bigint not null, description varchar(255) not null, label varchar(128) not null, primary key (id))

Я думал, что валидаторы будут работать автоматически. Что я здесь не так делаю?

1 Ответ

0 голосов
/ 27 июня 2018

Я думал, что валидаторы будут работать автоматически. Что я делаю здесь не так?

Вы сохраняете сущность, но не очищаете состояние текущего менеджера сущности.
Таким образом, проверка сущности еще не выполнена.

Вы можете обратиться к FAQ по валидатору Hibernate :

Почему моя сущность JPA не проверяется, когда я вызываю persist ()?

Почему моя сущность JPA не проверяется, когда я звоню persist()? Короткая ответ на звонок EntityManager#flush(), если вы хотите, чтобы проверка была срабатывает.

Hibernate ORM и несколько других ORM пытаются объединить столько операций, сколько возможно при доступе к базе данных. Вполне вероятно, что фактическое «персистентная» операция сущности происходит только когда вы звоните flush() или когда транзакция совершается.

Кроме того, знание того, какая сущность собирается сохраниться, зависит от вашего каскадная стратегия и состояние вашего объекта графа. Флеш это когда Hibernate ORM идентифицирует все объекты, которые были изменены, и требовать действий с базой данных (см. также HHH-8028).

Поэтому используйте JpaRepository.saveAndFlush() вместо JpaRepository.save(), чтобы разрешить проверку сущности.
Или, альтернативно, введите EntityManager или TestEntityManager в тестовый класс, вызовите JpaRepository.save(), а затем вызовите EntityManager/TestEntityManager.flush().

Для информации:

JpaRepository.save() вызывает em.persist(entity) / em.merge(entity)
JpaRepository.saveAndFlush() вызывает JpaRepository.save(), а затем em.flush()


Чтобы иметь возможность вызывать saveAndFlush(), вы должны сделать свой интерфейс репозитория расширенным JpaRepository, например:

public interface AuditEventRepository extends  JpaRepository<AuditEventEntity, UUID> {

Поскольку JpaRepository расширяет PagingAndSortingRepository, это изменение остается в соответствии с вашей существующей декларацией.


Я бы добавил, что это утверждение не требуется:

assertThat(saved.getLabel()).isNotNull();

То, что вы хотите утверждать, это то, что ValidationException выбрасывается и, возможно, содержит фактическое сообщение об ошибке.

...