Mock测试

本文详细介绍了Mock测试的概念,包括在单元测试中使用Mockito模拟复杂依赖和未完成模块的场景。通过一个具体的SourceController测试案例,展示了如何使用Mockito进行接口测试,包括Mockito.when和Mockito.doAnswer的使用方法,帮助读者理解如何有效地进行单元测试和接口测试。
摘要由CSDN通过智能技术生成

Mock测试

定义

对于单元测试,对于一些不容易构造获取的对象,或者对于尚未开发的模块,创建一个mock对象模拟对象的行为

何时使用mock测试

1、被依赖的对象构造复杂

class A 依赖 class B

class B 依赖 class Cclass D

class C 依赖 ...

class D 依赖 ...
    
比如我们想对A进行测试,而此时需要构造大量的class B、C、D等依赖对象,他们的构造过程复杂,此时可以利用mock构造虚拟的B、C、D对象对我们需要的A进行相关的测试

2、被依赖的模块尚未开发完成,而被测对象需要依赖模块的返回值进行测试

class AController{
    @Autowire
    private AService service;
    
    public void find(){
        service.findAll();
    }
}

此时我们的AService尚未构造成功,但我们需要对Acontroller进行测试,我们可以用mock虚拟构造Aservice并构造返回值

如何使用mock进行测试

有一个controller代码如下

import com.zhongkai.errorbook.service.SourceService;
import com.zhongkai.errorbook.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

/**
 * @author 17715
 * 用来查询以及增加错题来源
 */
@RestController
@RequestMapping("/source")
public class SourceController {

    @Autowired
    private SourceService sourceService;

    @GetMapping("/selectSource")
    public Result selectSource(String openid){
        return sourceService.selectSource(openid);
    }
}

此时需要对这个selectController的selectSource进行相关的测试

假设此时的sourceService还没开发完毕

此时的mock测试类为

import com.zhongkai.errorbook.mapper.SourceMapper;
import com.zhongkai.errorbook.service.SourceService;
import com.zhongkai.errorbook.service.impl.SourceServiceImpl;
import com.zhongkai.errorbook.util.CodeMsg;
import com.zhongkai.errorbook.util.Result;
import org.apache.commons.collections4.Get;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.result.StatusResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import java.sql.ResultSet;

/**
 * @author simba@onlying.cn
 * @date 2021/4/28 14:08
 */
@RunWith(SpringRunner.class)
public class SourceControllerTest {
    /**
     * MockMvc主要进行相关的web controller的测试
     */
    private MockMvc mockMvc;
    /**
     * @Mock表示对SourceController依赖的对象进行注入
     */
    @Mock
    private SourceService service;
    /**
     * @InjectMocks表示将@Mock的对象注入进SourceController
     */
    @InjectMocks
    private SourceController sourceController;

    /**
     * 进行相关的MockMvc的初始化
     */
    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(sourceController).build();
    }

    /**
     * 通过Mockmvc进行相关的接口请求
     * @throws Exception
     */
    @Test
    public void selectTest() throws Exception {
        String openid = "1235664";
        //构造service的虚拟对象,模拟返回值
        Mockito.when(service.selectSource(openid)).thenReturn(new Result(
                new CodeMsg(111, "测试成功")));
        //模拟对controller接口的调用,并进行相关的参数校验
        this.mockMvc.perform(MockMvcRequestBuilders.get("/source/selectSource").content(openid)
        ).andExpect(MockMvcResultMatchers.status().isOk());
    }

    /**
     * 不利用MockMvc进行相关的测试,而是直接调用controller进行相关的测试
     */
    @Test
    public void selectTest2() {
        String openid = "1235664";
        Result result = new Result(new CodeMsg(111, "测试成功"));
         /**
         * 此处也可以用 Mockito.when(service.selectSource(Mockito.anyString())).thenReturn(result);
         * Mockito可以生成任意的字符串、数字、或者复制对象(用any(Class class))生成
         */
        Mockito.when(service.selectSource(openid)).thenReturn(result);
        Result result1 = sourceController.selectSource(openid);
        Assert.assertEquals(result1, result);
    }
}

展示了两种测试controller的方法,对于接口的测试建议还是用第一种进行相关测试

Mockito.when与Mockito.doAnswer的讲解

Mockito.when

  Mockito.when(service.selectSource(openid)).thenReturn(new Result(
                new CodeMsg(111, "测试成功")));

when与thenReturn进行搭配,表示当执行某个方法的时候返回某个返回值,这个返回值在thenReturn中定义,常用于知道返回值的时候,且此时的参数信息不需要额外处理

Mockito.doAnswer

  Mockito.doAnswer(new Answer() {
            @Override
            public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
                NirvanaWizardProductDO wizardProductDO = invocationOnMock.getArgument(0);
                wizardProductDO.setId(1);
                return null;
            }
        }).when(service).updateStatus(wizardProductDO);

doAnswer表示当service执行updateStatus时返回answer方法返回的值,常用来处理参数信息需要额外处理的时候。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值