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 

  • 相关阅读:
    今天面试一些程序员(新,老)手的体会
    UVA 10635 Prince and Princess
    poj 2240 Arbitrage
    poj 2253 Frogger
    poj 2485 Highways
    UVA 11258 String Partition
    UVA 11151 Longest Palindrome
    poj 1125 Stockbroker Grapevine
    poj 1789 Truck History
    poj 3259 Wormholes
  • 原文地址:https://www.cnblogs.com/ceshi2016/p/9546669.html
Copyright © 2011-2022 走看看