这里以DemoController为例,Controller中调用了DemoService,代码如下:
@RestController
@RequestMapping("demo")
@Slf4j
public class DemoController {
    @Autowired
    private DemoService demoService;

    @GetMapping(value = "/service1")
    public String service1(String param1, Integer param2) {
        String result = demoService.service1(param1, param2);
        return result;
    }
    @GetMapping(value = "/service2")
    public Boolean service2(Long a, Long b) {
        Boolean result = demoService.service2(a, b);
        return result;
    }
    @GetMapping(value = "/service3")
    public DemoBean service3(String id) {
        DemoBean result = demoService.service3(id);
        return result;
    }
    @GetMapping(value = "/service4")
    public DemoBean service4(DemoBean demoBean) {
        DemoBean result = demoService.service4(demoBean);
        return result;
    }
}
public interface DemoService {
    String service1(String param1, Integer param2);
    Boolean service2(Long a, Long b);
    DemoBean service3(String id);
    DemoBean service4(DemoBean demoBean);
}

DemoService的实现类都返回null,代表未开发状态。

 
下面我们来看看怎么写这个controller的单元测试。
 
首先使用@InjectMocks注解DemoController:
@InjectMocks
private DemoController demoControllerMock;
 
然后使用@Mock注解controller中调用的第三方类,这里就是指DemoService:
@Mock
private DemoService demoService;
 
最后就是对应方法的测试方法了:
@Test
public void test01_01_service1() {
    //模拟动作
    Mockito.doReturn("aaa").when(demoService).service1(Mockito.anyString(), Mockito.anyInt());
    //调用接口
    String result = demoControllerMock.service1("abc", 233);
    log.info("service1 返回:" + result);
    //验证返回值
    Assert.assertEquals(result, "aaa");
}

模拟动作就是模拟controller中怎么调用service了,doReturn就是你想让service方法返回的值,when就是指模拟哪个service,service1就是实际调用的方法名了,参数Mockito.anyXxx()就是根据service方法的形参来的,这里代表任意符合参数类型的内容。

模拟动作配置好后,再调用接口,返回值就是模拟动作中doReturn中设置的内容了。
 
如果对应方法返回值是实体类或集合类型,就需要首先将数据组织起来:
@Test
public void test03_01_service3() {
    //组织数据
    DemoBean demoBean = new DemoBean();
    demoBean.setName("wang");
    demoBean.setNumber(200);
    List<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    demoBean.setList(list);
    //模拟动作
    Mockito.doReturn(demoBean).when(demoService).service3(Mockito.anyString());
    //调用接口
    DemoBean result = demoControllerMock.service3("abc");
    log.info("service3 返回:" + JSON.toJSONString(result));
    //验证返回值
    Assert.assertNotNull(result);
}

如果第三方类不是service,而是远程调用接口的话,需要先获取远程调用接口的返回json串:

//组织数据
String returnStr = "{\"timeStamp\": \"1560131834846\", \"returnCode\": \"0000\", \"beans\": [], \"returnMessage\": \"sucess\",\"bean\": {} }";
然后封装成远程调用的response
//模拟动作
Mockito.doReturn(response).when(iXxxSV).service(Mockito.any());
这样,当代码运行到远程调用接口时,就不会去请求远程接口,而是直接返回response的内容了。
 
增加对异常分支的支持:
Controller:
@GetMapping(value = "/service5")
public DemoBean service5(String id) {
    DemoBean result = null;
    try {
        result = demoService.service5(id);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

Service:
DemoBean service5(String id) throws Exception;

Test:
@Test
public void service5() throws Exception {
    //模拟动作
    Mockito.doThrow(new Exception("模拟覆盖异常分支")).when(demoService).service5(Mockito.any());
    //如果第三方接口没有throw异常,上面这句会报错,需要如下写法
    Mockito.doThrow(Exception.class).when(demoService).service5(Mockito.any());
    DemoBean result = demoControllerMock.service5("abc");
    log.info("service5 返回:" + JSON.toJSONString(result));
    Assert.assertNull(result);
}
 
 
最后修改于 2019-07-19 14:35:42
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付
上一篇