java – 在单元测试中调用Spring Repository.save()时未触发Hibernate Validator

这是我的实体:

@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”字段为null,保存也会成功!

@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))

我认为验证器会自动运行.我在这做错了什么?

最佳答案

I thought the validators would work automatically. What am I doing
wrong here?

您保存实体但不刷新当前实体管理器的状态.
因此,尚未执行实体的验证.

你可以参考Hibernate validator FAQ

Why is my JPA entity not validated when I call persist()?

Why is my JPA entity not validated when I call persist()? The short
answer is call EntityManager#flush() if you want the validation to be
triggered.

Hibernate ORM and a few other ORMs try to batch as many operations as
possible when accessing the database. It is likely that the actual
entity “persist” operation only happens when you call flush() or when
the transaction commits.

Also, knowing which entity is about to be persisted depends on your
cascading strategy and the state of your object graph. Flush is when
Hibernate ORM identifies all the entities that have been changed and
require database actions (see also 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(),您必须使您的Repository接口扩展JpaRepository,例如:

public interface AuditEventRepository extends  JpaRepository<AuditEventEntity, UUID> {

由于JpaRepository扩展了PagingAndSortingRepository,因此此更改与您现有的声明保持一致.

我想补充一点,这个断言不是必需的:

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

你要断言的是抛出ValidationException,也许它包含实际的错误消息.

转载注明原文:java – 在单元测试中调用Spring Repository.save()时未触发Hibernate Validator - 代码日志