zoukankan      html  css  js  c++  java
  • Spring Boot中采用Mockito来mock所测试的类的依赖(避免加载spring bean,避免启动服务器)

    最近试用了一下Mockito,感觉真的挺方便的。举几个应用实例:

    1,需要测试的service中注入的有一个dao,而我并不需要去测试这个dao的逻辑,只需要对service进行测试。这个时候怎么办呢,mockito就可以做到把这个dao给mock了,调用这个dao的方法会直接返回预设的值,不会去真正的执行dao里的逻辑,省时省力,专注于眼前。

    2,不想在单测时启动容器,加载一堆没有用的东西。这个时候你就可以把你的单元测试写成一个纯junit的test类,可以飞快的跑完测试逻辑,不用等待server加载,spring加载等乱七八糟的过程。当然这个只是一个附带的好处,主要还是1。

    下面写来一段简单的代码,稍作讲解(项目基于spring boot,其实无所谓,只要有junit,mockito,spring依赖即可,数据库配置什么的也需要自己已经配好了,这里不做说明)。

    先来实体类:

    /**
     * Created by zp on 2017/11/20.
     */
    @Data
    @Builder
    @Entity
    @Table
    public class Model {
        private Long id;
        private String name;
    }

    Lombok注解就不多解释了。标准Bean

    DAO:

    /**
     * Created by zp on 2017/11/20.
     */
    @Repository
    public class ModelDao {
        public Model getModel(Long id){
            return Model.builder().id(id).name("model from dao ").build();
        }
    }

    最简单的dao,实际上应该是访问数据库,为了方便,这里构建一个对象返回出去。注意name是model from dao,由这个dao得出的对象name都会是这个,mock出来的会是另一个。

    Service:

    /**
     * Created by zp on 2017/11/20.
     */
    @Service public class ModelServiceImpl implements ModelService { @Autowired ModelDao modelDao; @Override public Model getModel(Long id) { return modelDao.getModel(id); } }

    接口的实现类,ModelService就一个方法,这里不写了。

    好了,基础的service和dao,bean都有了。现在我们要对ModelService做测试,按照传统的方式,Tests代码如下:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class DemoApplicationTests {
    
        @Autowired
        ModelService modelService;
    
    
        @Test
        public void contextLoads() {
            Model model = modelService.getModel(3L);
            System.out.println(model);
            Assert.assertEquals(3l,model.getId().longValue());
        }
    
    }

    这个会加载spring的一堆依赖,然后按照spring的注入规则,把ModelService注入进来,同时也会把ModelDao注入到ModelService中,运行一下,熟悉的画面:

    单测会顺利通过:

    控制台也会打印如下输出:

     

     可见这个是真的走的dao的代码逻辑,如果是真实业务代码,那这就去读数据库了。

    这个流程虽然也能跑,但是牵扯的东西太多,还要保证ModelDao能正确注入,运行;还要加载一堆spring/server的东西,耗时耗力。

    下面就用mockito来改写一下Tests代码,结果如下:

    public class DemoApplicationTests {
    
        @InjectMocks
        private ModelService modelService= new ModelServiceImpl();
    
        @Mock
        private ModelDao modelDao;
    
    
        @Before
        public void setUp() {
            MockitoAnnotations.initMocks(this);
    
            when(modelDao.getModel(any(Long.class)))
                    .thenReturn(Model.builder().id(1L).name("model from mock").build());
        }
    
        @Test
        public void contextLoads() {
            Model model = modelService.getModel(3L);
            System.out.println(model);
            Assert.assertEquals(3l,model.getId().longValue());
        }
    
    }

    主要有以下几点变化:

    1,@RunWith(SpringRunner.class),@SpringBootTest这两个注解去掉,整个Test清除了Spring Test依赖,可以避免加载额外的东西;

    2,Autowire 改成如下:

        @InjectMocks                                                  
        private ModelService modelService= new ModelServiceImpl();    

    不再Autowire,而是InjetMocks,并且要自己new出Service对象;

    3,添加Mock Dao的代码

    @Mock                       
    private ModelDao modelDao;  

    表示这个对象是需要Mock的

    4,初始化Mockito,编写Mock逻辑

    @Before
        public void setUp() {
            MockitoAnnotations.initMocks(this);
    
            when(modelDao.getModel(any(Long.class)))
                    .thenReturn(Model.builder().id(1L).name("model from mock").build());
        }

    重点在when()这个方法里,when函数以需要mock的方法作为参数,any表示任何输入,thenReturn设置返回的值。

    这句when的意思就是当碰到modelDao的getModel函数,传入参数为任何一个Long,则直接返回一个新的,自己构建的Model对象,避免执行ModelDao的真实代码。

    先看一下代码,mock后ModelDao无论输入任何参数,都会返回一个id为1,name为model from mock的Model对象,这个单测肯定是跑不过的。让我们来验证一下:

    果然跟我们预期的一样,并且完全没有加载spring,直接一下就跑完了测试。

  • 相关阅读:
    Milking Time---poj3616(简单dp)
    elasticsearch-入门(一)
    Spring Cloud Sleuth(十四)
    Spring Cloud Stream(十三)
    Spring Cloud-Bus(十二)
    Spring Cloud-config(十一)
    mac Gitblit安装
    git学习笔记
    java陷阱之spring事物管理导致锁无效
    Spring Cloud-Zuul(十)
  • 原文地址:https://www.cnblogs.com/csonezp/p/7868127.html
Copyright © 2011-2022 走看看