在Spring上模拟@Validated注释控制器方法的ConstraintValidator

在Spring上模拟@Validated注释控制器方法的ConstraintValidator,spring,spring-mvc,spring-boot,mockmvc,spring-validator,Spring,Spring Mvc,Spring Boot,Mockmvc,Spring Validator,使用SpringBoot1.3.6.RELEASE,我尝试使用Junit、Mockito和MockMvc对控制器方法进行单元测试。我已经构建了一个自定义约束验证器(扩展),用于自动连接服务。我的目标实体使用自定义验证器注释和一个组进行注释。我的控制器方法签名如下所示: @RequestMapping ( value = "api/task/newtask", method = RequestMethod.POST ) public ResponseEntity submitTask ( @Val

使用SpringBoot1.3.6.RELEASE,我尝试使用Junit、Mockito和MockMvc对控制器方法进行单元测试。我已经构建了一个自定义约束验证器(扩展),用于自动连接服务。我的目标实体使用自定义验证器注释和一个组进行注释。我的控制器方法签名如下所示:
@RequestMapping ( value = "api/task/newtask", method = RequestMethod.POST )
public ResponseEntity submitTask ( @Validated ( value = TaskDependenciesDbValidation.class ) 
                                   @RequestBody Task task )

您可以使用以下方法完全模拟验证器:

对于您的示例,如果您正在对控制器进行单元测试,为什么要显示整个Spring上下文?因为这就是你要做的

@RunWith ( SpringJUnit4ClassRunner.class )
@SpringApplicationConfiguration ( classes = MyApplication.class )
@ContextConfiguration ( classes = MockServletContext.class )
@WebAppConfiguration

首先也是最重要的一点是,您应该删除这些内容并重试

我是通过跟随tomasz_kusmierczyk来实现的

可以找到我创建的约束验证工厂和“测试验证器”的创建

我的自定义验证器(
TicketExistsValidator
UsersExistValidator
)在内部使用服务(
TicketService
UserService
)。我在测试中创建这些服务的模拟,然后将模拟的服务传递给工厂(工厂随后使用验证器的名称来设置模拟服务)

之后,可以使用mockito.when()模拟服务


为了让注释约束(@NotNull,@Size)在测试中起作用,我必须用@Valid和@Validated(CustomGroup.java)对我的控制器进行注释。

你能添加你编写的测试吗?是的,添加你的测试代码会非常有帮助,没有它,我们只能猜测出了什么问题。添加了一次测试尝试。我所做的另一个尝试是在测试类声明和测试方法中使用@Mock注释验证器:when(myValidator.isValid(any..,any..)。然后返回(true);相关:解决了尼斯的解决方案。对于我来说,imho是不是比配置一个单独的TestingContrainValidatorFactory更好的解决方案,它支持特定模拟的DI。亲爱的@Alextsil代码看起来很整洁,但在设置完所有内容后,测试时仍然忽略了我的验证器。我拥有像你一样的一切。我有一个定制的验证器及其接口,并且像您一样添加了验证工厂(在验证器调用内部服务时在其中添加我自己的服务)。然后我从工厂获取LocalValidatorFactoryBean,并将其添加到带有.setValidator的mockMvc中,但它仍然没有进入我的自定义验证器,而是从controller方法开始。你能给我一些关于可能发生什么或者如何调试它的提示吗?
@RunWith ( SpringJUnit4ClassRunner.class )
@SpringApplicationConfiguration ( classes = MyApplication.class )
@ContextConfiguration ( classes = MockServletContext.class )
@WebAppConfiguration
public class TaskControllerTests
{
    @InjectMocks
    TaskController taskController;
    @Mock
    TaskService taskService;
    @Mock
    TicketService ticketService;
    .
    .
    @Before
    public void setup ()
    {
        MockitoAnnotations.initMocks( this );
        mockMvc = standaloneSetup( this.taskController )
            .setControllerAdvice( new RestExceptionHandler() )
            .build();
    }
    .
    .
    @Test
    public void submitTask () throws Exception
    {
        when( taskService.create( any( Task.class ) ) ).thenReturn( this.task );
        doNothing().when( ticketService ).verifyTicketExists( 1L );
        mockMvc.perform( post( "/api/task/newtask" ).content( "..validpayload..") ).andExpect( status().isCreated() );
    }
}
public class Test {

    @Mocked // mocks the class everywhere
    TaskDependenciesDbConstraintValidator validator;

    @Test
    public void testMethod(){
        new Expectations {{ // expect the validator to be called
            validator.isValid((Ticket) any, (ConstraintValidatorContext) any);
            result = true; // and declare the object to be valid
        }}

        // do your testing here
    }
}
@RunWith ( SpringJUnit4ClassRunner.class )
@SpringApplicationConfiguration ( classes = MyApplication.class )
@ContextConfiguration ( classes = MockServletContext.class )
@WebAppConfiguration