繁体   English   中英

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

[英]Hibernate Validator not triggered as Spring Repository.save() is invoked in unit tests

这是我的实体:

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

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

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

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

您可以参考Hibernate验证器FAQ

为什么在调用persist()时我的JPA实体未经过验证?

为什么在调用persist()时我的JPA实体未经过验证? 如果您希望触发验证,简短的答案是调用EntityManager#flush()

Hibernate ORM和其他一些ORM尝试在访问数据库时批量尽可能多的操作。 实际的实体“持久化”操作可能只在您调用flush()或事务提交时发生。

此外,了解哪个实体将被持久化取决于您的级联策略和对象图的状态。 刷新是指Hibernate ORM识别出已更改并需要数据库操作的所有实体(另请参阅HHH-8028)。

因此,使用JpaRepository.saveAndFlush()而不是JpaRepository.save()来允许实体进行验证。
或者,在测试类中注入EntityManagerTestEntityManager ,调用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 ,也许它包含实际的错误消息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM