zoukankan      html  css  js  c++  java
  • Springboot单元测试(MockBean||SpyBean)

    转载:https://blog.csdn.net/maiyikai/article/details/78483423

    本来要写springboot集成netty实现的,但是想起来单元测试没总结,那就趁此机会总结一下,不用文字了,直接用代码去实现: 
    创建一个放方法的类MethodTest.java:(命名不严谨,能看懂就行了)

    package com.mtk.netty.test;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class MethodTest {
    
        //主方法
        public String gg(boolean flag){
            System.err.println("coming.........");
            String d = g(flag);//子方法
            h();
            System.err.println("result data is "+d);
            return d;
        }
    
        public String g(boolean flag){
            System.err.println("coming.........g");
            if(flag){
                throw new IllegalAccessError();//flag为true时抛异常
            }
            return "d";
        }
    
        public void h(){
            System.err.println("coming.........h");
        }
    }

    使用上边的方法类,写单元测试: 
    这里时spy方式:

    package com.mtk.netty.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.Mockito;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.mock.mockito.SpyBean;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.context.web.WebAppConfiguration;
    
    import com.myk.Application;
    
    /**
     * 使用spy方式
     * @author maiyikai 2017.11.08
     *
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest(classes = Application.class)
    @WebAppConfiguration
    public class SpyTest {
        //gg(boolean)方法:控制台打印: coming.........
        //g(boolean)方法:控制台打印: coming.........g
        //h()方法:控制台打印: coming.........h
        //gg(boolean)方法在g(boolean)和h()方法执行完之后:控制台打印: result data is *
    
        /**
         * 使用代理:如下方式
         * 或Mockito.spy(MethodTest.class)获得代理对象
         */
        @SpyBean
        private MethodTest spyTest;
    
        /**
         * 不代理,直接运行程序
         * 控制台打印:
         *  coming.........
         *  coming.........g
         *  coming.........h
         *  result data is d
         *  d
         */
        @Test
        public void test(){
            System.err.println(spyTest.gg(false));
        }
    
        /**
         * 不使用代理:让g方法抛异常
         * 控制台打印
         * coming.........
         * coming.........g
         * 由于抛异常,程序中断
         */
        @Test
        public void test2(){
            System.err.println(spyTest.gg(true));
        }
    
        /**
         * 使用代理对象,代理g方法,并让其返回“test”
         * 第一种方式:使用thenReturn("test");
         * 控制台打印:
         * coming.........g
         * coming.........
         * coming.........h
         * result data is test
         * test
         * 
         */
        @Test
        public void test3(){
            Mockito.when(spyTest.g(false)).thenReturn("test");
    
            System.err.println(spyTest.gg(false));
        }
        /**
         * 使用代理对象,代理g方法,并让其返回“test”
         * 第二种方式:使用doReturn("test");
         * 其中doReturn("test")后执行.when(spyTest).g(false)方法
         * 控制台打印:
         * coming.........
         * coming.........h
         * result data is test
         * test
         * 
         */
        @Test
        public void test4(){
            Mockito.doReturn("test").when(spyTest).g(false);
            System.err.println(spyTest.gg(false));
        }
        /**
         * test3-test4比较
         * 正常执行顺序
         *  coming.........
         *  coming.........g
         *  coming.........h
         *  result data is d
         *  d
         * 使用Mockito.when(spyTest.g(false)).thenReturn("test");方式
         * g(boolean)方法会在调用主方法gg(boolean)前执行,不管执行的结果是啥,都会按照mock的数据“test”返回
         * 
         * 使用Mockito.doReturn("test").when(spyTest).g(false);方式
         * g(boolean)方法不会被执行,当时会将它的返回值赋值为:“test”。
         * 在主方法gg(boolean)执行到g(boolean)时,不执行g(boolean)方法体,直接将值“test'”返回。后续方法照常执行 
         */
    //#######################################################################################   
        /**
         * 使用代理对象,代理gg方法,并让其返回“test”
         * 第一种方式:使用thenReturn("test");
         * 控制台打印:
         * coming.........g
         * 
         */
        @Test
        public void test5(){
            Mockito.when(spyTest.g(true)).thenReturn("test");
            System.err.println(spyTest.gg(true));
        }
    
        /**
         * 使用代理对象,代理gg方法,并让其返回“test”
         * 第二种方式:使用doReturn("test");
         * 其中doReturn("test")后执行.when(spyTest).g(true)方法--抛异常
         * 控制台打印:
         * coming.........
         * coming.........h
         * result data is test
         * test
         * 
         */
        @Test
        public void test6(){
            Mockito.doReturn("test").when(spyTest).g(true);
            System.err.println(spyTest.gg(true));
        }
    
        /**
         * test5-test6比较
         * 故意赋值让其方法抛异常。
         * 正常执行顺序
         *  coming.........
         *  coming.........g
         *  coming.........h
         *  result data is d
         *  d 
         * 
         *  因为:Mockito.when(spyTest.g(true)).thenReturn("test");会执行方法体的内容,则g(boolean)方法体会被执行,会抛出异常中断程序运行
         *  而Mockito.doReturn("test").when(spyTest).g(true);方法体不会被执行,则不会抛出异常,不会造成程序中断
         */
    
        //##################################无返回值######################
        /**
         * 无返回值方法的代理
         * 方法为h()
         * 因此方法对代码不造成任何影响,所以可以不执行它
         * 可以使用:doNothing
         * 代码:Mockito.doNothing().when(spyTest).h();
         */
        @Test
        public void test7(){
            Mockito.doNothing().when(spyTest).h();
    
            System.err.println(spyTest.gg(false));
        }
    
        /**
         * 测试
         * coming.........
         * coming.........g
         * result data is d
         * d
         */
        @Test
        public void test10(){
            Mockito.doReturn("23").when(spyTest).g(true);
            Mockito.doNothing().when(spyTest).h();
    
            System.err.println(spyTest.gg(false));
        }
    }

    这里时mock的方式:

    package com.mtk.netty.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.Mockito;
    import org.mockito.invocation.InvocationOnMock;
    import org.mockito.stubbing.Answer;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.mock.mockito.MockBean;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.context.web.WebAppConfiguration;
    
    import com.myk.Application;
    
    /**
     * 使用mock方式
     * @author maiyikai 2017.11.08
     *
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest(classes = Application.class)
    @WebAppConfiguration
    public class MockTest {
    
        //gg(boolean)方法:控制台打印: coming.........
        //g(boolean)方法:控制台打印: coming.........g
        //h()方法:控制台打印: coming.........h
        //gg(boolean)方法在g(boolean)和h()方法执行完之后:控制台打印: result data is *
    
    
            /**
             * 使用代理:如下方式
             * 或Mockito.mock(MethodTest.class)获得代理对象
             */
            @MockBean
            private MethodTest mockTest;
    
    
    
            /**
             * 使用mock方式将会把对象给mock掉,则对象中的方法将不会被执行,但是使用到某方法时可以mock值,供调用方法使用
             */
    
            /**
             * 访问主方法体gg(boolean)
             * 返回null
             */
            @Test
            public void test1(){
                System.err.println(mockTest.gg(false));
            }
    
            /**
             * mock方法gg(boolean),使其在使用到gg(boolean)方法时,返回:"test"
             */
            @Test
            public void test2(){
                Mockito.when(mockTest.gg(false)).thenReturn("test");
    
                System.err.println(mockTest.gg(false));
            }
            /**
             * mock方法gg(boolean),使其在使用到gg(boolean)方法时,返回:"test"
             */
            @Test
            public void test3(){
                Mockito.doReturn("test").when(mockTest).gg(false);
    
                System.err.println(mockTest.gg(false));
            }
            /**
             * mock方法gg(boolean),使其在使用到gg(boolean)方法时,返回:"test"
             */
            @Test
            public void test4(){
                Mockito.when(mockTest.gg(false)).thenAnswer(new Answer<String>() {
                    //Answer<T>   T为方法的返回值类型
                    @Override
                    public String answer(InvocationOnMock invocation) throws Throwable {
                        return "test";
                    }
                });
    
                System.err.println(mockTest.gg(false));
            }
            /**
             * mock方法gg(boolean),使其在执行到此方法时抛出自定义异常
             */
            @Test
            public void test5(){
                Mockito.when(mockTest.gg(false)).thenThrow( new IllegalArgumentException("单元测试异常"));
    
                System.err.println(mockTest.gg(false));
            }
    
            //对与返回值类型为void的操作有
            //1.直接mock对象,即此对象中所有的方法都不会被执行
            //2.使用Mockito.doNothing().when(mockObject).method();标记执行该方法时不做任何操作
    }

    因时间有限,写了一些简单的操作; 
    写单元测试的过程中,有想过“只需要mock方法类中的某个方法,其他的方法不受影响”;之前使用MockBean就出问题了,研究了一下使用SpyBean就可以使用了,可以看上边的例子就可以知道了。 
    springboot的文档介绍也是可以看的:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html “springboot 
    我的项目上传地址:http://download.csdn.net/download/maiyikai/10110450 

  • 相关阅读:
    ELK+Kafka+Beats实现海量日志收集平台(三)
    ELK+Kafka+Beats实现海量日志收集平台(二)
    ELK+Kafka+Beats实现海量日志收集平台(一)
    Linux 上安装logstash-6.6.0及配置kafka输入
    Linux 上安装filebeat-6.6.0
    SpringBoot与Kafka整合实现简单分布式消息队列
    logstash-6.6.0.tar.gz、filebeat-6.6.0-linux-x86_64.tar.gz 下载百度云
    Centos 7.X 上安装Kafka及一些常用命令
    Linux MariaDB 10.4.8 官网地址下载及百度云
    [Errno 28] No space left on device ERROR: Could not install packages due to an EnvironmentError
  • 原文地址:https://www.cnblogs.com/ceshi2016/p/9546669.html
Copyright © 2011-2022 走看看