0


Mock单元测试----对Controller层进行单独测试,不调用Service层

前言:根据相关需求,需要对编写的代码进行逻辑检测以及功能的完整性,从而开始了单元测试之路。在编写的中间段时,突然被 不经过Service层直接测试Controller层 这个要求难住了。在我看来,单元测试除了Junit还是Junit,属实是学艺不精,之后接触了Mock,才发现Mock太牛逼了,爱死了。

回归正题,单独使用Juit测试,我目前是不太会的,而且需要保证使用Controller层时不调用Service,还要对Controller的返回值进行验证,对于刚开始接触Mock单元测试的人来说肯定是个难点。

例如:我们要对Controller类中的select方法类进行一个测试,保证其能够顺利执行Service的selectComment方法,但是要求不能调用此方法,怎么做呢?

@Override
    public RestResponse<CareCourseComment> select(CareCourseComment careCourseComment){
        return targetService.selectComment(careCourseComment);
    }

这里不再赘述mock的配置和依赖,请自行装配!

在测试类中,我们首先需要进行Controller层和Service层的自动装配

    @Autowired
    private CareCourseCommentService targetService;
    @Autowired
    private CareCourseCommentController targetController;

然后实现代码如图所示,接下来慢慢解释

    @Test
    public void testSelectControllerTest() throws Exception{
        RestResponse<IPage<CareCourseComment>> list = new RestResponse<>();
        //数据定义
        CareCourseComment careCourseComment = new CareCourseComment();
        careCourseComment.setOpenid("533412d");
        Map careCourseCommentMaps = JSON.parseObject(JSON.toJSONStringWithDateFormat(careCourseComment,"yyyy-MM-dd HH:mm:ss"),Map.class);
        //mock模拟Service
        CareCourseCommentService careCourseCommentService = mock(CareCourseCommentService.class);
        //设置范围
        ReflectionTestUtils.setField(targetController,"targetService",careCourseCommentService );
        when(careCourseCommentService.selectComment(any())).thenReturn(list);
        //进行实际输入验证
        RestResponse<IPage<CareCourseComment>> careList = targetController.select(careCourseCommentMaps);
        //重置模拟,进行还原
        ReflectionTestUtils.setField(targetController,"targetService",targetService);
        //断言,结果比对
        assertEquals(list,careList);
    }

这里的RestResponse是应答响应,和ApiResponse一样,有code、message和data。因为addComment是返回RestResponse,所以这里的Controller类接收到的也是RestResponse。后面的两行是进行数据的模拟,Service类是接收的Map类型的,所以需要进行类型转换(这里的JSON.toJSONStringWithDateFormat中的"yyyy-MM-dd HH:mm:ss"主要是对入参时的时间进行格式转换,防止传入的时间变成时间戳格式,然后可能之后再用SimpleDateFormat转换时变成CST格式,真的是太心累了)。

之后我们需要首先对Service进行mock的模拟,根据要求我们不能真的调用Service,直接使用mock来进行模拟,令它返回一个我们想要的值。接下来就是重点了!我们需要先对测试进行一个范围限制,将他限制在Controller层的targetService里,当我们使用Controller层的targetService时,它调用的是我们模拟的Service,而不是@Autowired自动装配的原有的Service。

when().thenReturn()方法用于确认当我执行到Service的selectComment时,不管我传入的是什么值,都会返回我定义的list,之后便是进行实际的输入验证,将前面定义的数据传到Controller层的select方法中进行实际的验证,然后进行结果比对。

这里需要注意:在验证完后需要对Controller的targetService进行还原!!!否则会导致其他的测试类也会被这个mock模拟的Service所替换。可能导致当整一个测试类进行运行时,会使得其他的测试类与预期结果出现大偏差甚至报错,在debug的过程下,可以清楚地看到Controller层的targetSerice是由mock模拟的。


本文转载自: https://blog.csdn.net/Sourbing/article/details/125507245
版权归原作者 樾云枫 所有, 如有侵权,请联系我们删除。

“Mock单元测试----对Controller层进行单独测试,不调用Service层”的评论:

还没有评论