zoukankan      html  css  js  c++  java
  • spring /spring boot中mock

    1 Mockito简介

    1.1 Mockito是什么

      Mockito是一个简单的流行的Mock框架。它允许你创建和配置mock对象。使用Mockito可以明显的简化对外部依赖的测试类的开发。一般使用 Mockito 需要执行下面三步: 
     模拟并替换测试代码中外部依赖;
     执行测试代码;
     验证测试代码是否被正确的执行。

    1.2 Mock是什么

      Mock测试就是在测试过程中,对某些不容易构造或者不容易获取的对象,用一个虚拟的Mock对象来创建以便测试的测试方法。
      Mock最大的功能是帮你把单元测试的耦合分解开,如果你的代码对另一个类或者接口有依赖,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为。

    2 Mockito在Spring框架中的使用

    2.1 依赖包

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>2.21.0</version>
        <scope>test</scope>
    </dependency>

    Mockito在Spring可以通过配置文件和注解的方式使用

    2.2 通过xml配置文件使用Mockito

      Mockito创建方式有两种:mock,spy。mock为一个interface提供一个虚拟的实现,spy为object加一个动态代理,实现部分方法的虚拟化,但是需要赋予一个instance。
      Mockito提供了factory的方法用来创建mock和spy。
      假设构造系统中有serviceA,serviceB,serviceC,其中serviceA依赖serviceB依赖serviceC。serviceC是最基本的。现在需要对其中serviceA进行测试,但其serviceC需要依赖于外部环境,而这个环境需要复杂而且不稳定的数据库。这时需要mock或spy掉serviceC。

    注:无论是spring框架还是spring boot框架,如果集成了MyBatis,因Mybatis中Mapper基于动态代理实现,则其对应的mapper接口只能基于xml文件配置方式注入mock或spy。
    具体解释参考:https://sq.163yun.com/blog/article/169561874192850944

    第一步:在配置文件中注入mock:

    <bean id="serviceC"  class="org.mockito.Mockito"factory-method="mock">
        <constructor-arg value="com.x.y.x.ServiceC"></constructor-arg>
    </bean>

    或注入spy

    <bean id="serviceCInst"  class="serviceCInstance">
    </bean>
    <bean id="serviceC"  class="org.mockito.Mockito" factory-method="spy">
           <constructor-arg ref="serviceCInst"></constructor-arg>
    </bean>

    spy需要获得一个实例。

    第二步:

    在测试用例中@Resource或@Autowired引入serviceC。

    2.3 通过注解使用Mockito

    以代码举例

    @Component
    public class OrderCreate {
     
        @Resource
        private OrderHelper orderHelper;
     
        public void create() {
            System.out.println(getAmt());
            System.out.println(orderHelper.resolve());
        }
     
        public int getAmt() {
            return 10;
        }
    }
    @Component
    public class OrderHelper {
        public String resolve() {
            return "resolve order";
        }
    }

    测试类:

    public class MockSpringTest {
     
        @InjectMocks
        private OrderCreate orderCreate;
         
        @Mock
        private OrderHelper orderHelper; // 此mock将被注入到orderCreate
     
        @Before
        public void initMocks() throws Exception {
            MockitoAnnotations.initMocks(this);
        }
     
        @Test
        public void create() {
            System.out.println("start mock...");
            when(orderHelper.resolve()).thenReturn("null");
            orderCreate.create();
        }
    }

    运行结果:

    start mock...
    10
    null

    mock() / @Mock:创建一个mock;
    spy() / @Spy:创建一个spy,提供了一种对真实对象操作的方法;
    @InjectMocks:创建一个实例。被@Mock(或@Spy)注解创建的mock将被注入到用该实例中。注意: @InjectMocks标注的属性不能使用接口。

    3 Mockito在Spring boot 框架中的使用

    3.1 Spring Boot自带测试模块

      Spring boot自身提供很多有用的工具类和注解用于测试应用,主要分两个模块:spring-boot-test包含核心组件,spring-boot-test-autoconfigure为测试提供自动配置。开发者只需要引用spring-boot-starter-test即可。它提供的测试模块中包含了Mockito。
      Spring boot使用@MockBean和@SpyBean来定义Mockito的mock和spy。SpringBoot提供的@MockBean注解,用于为Applicatio nContext中的bean定义一个mock,你可以使用该注解添加新beans,或替换已存在的bean定义。该注解可直接用于测试类,也可用于测试类的字段,或用于@Configuration注解的类和字段。当用于字段时,创建mock的实例也会被注入。Mock beans每次调用完测试方法后会自动重置。

    以代码举例:

    @Component
    public class MethodTest {
     
       public String One(boolean flag){
           System.err.println("coming.........");
           String d = Two(flag);
           Three();
           System.err.println("result data is "+d);
           return d;
       }
     
       public String Two(boolean flag){
           System.err.println("coming.........two");
           if(flag){
               throw new IllegalAccessError();
           }
           return "two";
       }
     
       public void Three(){
           System.err.println("coming.........three");
       }
    }

    测试类 @SpyBean

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = DemoApplication.class)
    public class SpyTest{
           @SpyBean
           private MethodTest spyTest;
           @Test
           public void test3(){
               when(spyTest.Two(false)).thenReturn("test");
               System.err.println(spyTest.One(false));
       }
    }

    运行结果:

    coming.........two
    coming.........
    coming.........three
    result data is test
    test

    测试类 @MockBean

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = DemoApplication.class)
    public class MockTest{
       @MockBean
       private MethodTest mockTest;
       @Test
       public void test3(){
           when(mockTest.One(false)).thenReturn("test");
           System.err.println(mockTest.One(false));
       }
    }

    运行结果:

    test

    3.2 Spring Boot使用原生Mockito

           使用方式见第2部分。

    4 总结

      为了统一springBoot和spring项目对Mockito的配置方式,同时解决框架中Mybaties之Mapper动态代理的mock场景,建议统一使用xml文件配置的方式。

  • 相关阅读:
    守卫者的挑战(guard)
    pf
    放砖头
    多人背包
    TC-572-D1L2 未完!待续!
    方程的解数
    单词矩阵/贰五语言
    虫食算
    移动玩具
    UVA 125 统计路径条数 FLOYD
  • 原文地址:https://www.cnblogs.com/ceshi2016/p/9550823.html
Copyright © 2011-2022 走看看