使用Spring Boot执行@WebMvcTest时,是否有办法获取注入自定义bean验证器中的EntityManager实例?

问题描述

我创建了一个自定义bean验证器,如下所示:

public class UniqueValidator implements ConstraintValidator<Unique,Object> {

    private final EntityManager entityManager;
    private Class<?> entityClass;
    private String entityField;

    public UniqueValidator(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public void initialize(Unique constraint) {
        entityClass = constraint.entityClass();
        entityField = constraint.entityField();
    }

    public boolean isValid(Object value,ConstraintValidatorContext context) {
        return !ExistsValidation.exists(entityManager,entityClass,entityField,value);
    }

}

它工作得很好,但是当我在测试上下文中命中端点时,EntityManager不会被注入并抛出异常:Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

那是我要开始工作的测试:

@WebMvcTest(ProposalController.class)
class ProposalControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @MockBean
    private ProposalRepository proposalRepository;

    @Test
    public void testCreateProposal() throws Exception {
        // given
        var request = new ProposalRequest(
                "Tânia","Bárbara Mendes","159.296.683-70","taniabarbaramendes@yazigi.com",LocalDate.of(2000,12,9));
        ArgumentCaptor<Proposal> captor = ArgumentCaptor.forClass(Proposal.class);

        // when
        MockHttpServletResponse response = mockMvc.perform(
                post("/proposals").contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(request)))
                .andReturn().getResponse();

        // then
        verify(proposalRepository,times(1)).save(captor.capture());

        assertThat(captor.getValue()).isEqualToComparingFieldByField(request.toProposal());
        assertThat(response.getStatus()).isEqualTo(CREATED.value());
    }
}

在执行上述测试方案时,如何将EntityManager注入到自定义bean验证程序中?

解决方法

有多种提供EntityManager的方法。但我假设对于此测试,您想模拟它以控制其行为。

为此,只需添加

@MockBean
private EntityManager entityManager;

...,您将在切片后的Spring Context中获得EntityManager的模拟版本。

对于 real EntityManager,您必须提供测试数据库。您可以使用内存数据库,也可以使用Testcontainers使用Docker启动数据库。

然后您可以在同一测试上组合@WebMvcTest@DataJpaTest并获得带有所有JPA和MVC相关组件的切片Spring Context。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...