zoukankan      html  css  js  c++  java
  • Mock、Powermock使用汇总

    背景

    工作中经常用到单测,某对单测掌握的不好,所以趁此学习、总结一下。

    主要参考:https://www.jianshu.com/p/0c2480b1709e、https://www.cnblogs.com/ljw-bim/p/9391770.html

    一、不依赖外部方法的单测

    1、待测试类

    package com.shuimutong.demo.junit;
    
    /**
     * 无依赖方法
     * @ClassName:  NotStaticMethod   
     * @Description:(这里用一句话描述这个类的作用)   
     * @author: 水木桶
     * @date:   2019年10月26日 上午10:37:09     
     * @Copyright: 2019 [水木桶]  All rights reserved.
     */
    public class NoRelayMethod {
        public static int ADD_NUM = 2;
        
        public static int staticAddTwo(int num) {
            return num + ADD_NUM;
        }
        
        /**
         * 非静态方法
         * @param num
         * @return
         */
        public int notStaticAddTwo(int num) {
            return num + ADD_NUM;
        }
        
        /**
         * 私有非静态方法
         * @param num
         * @return
         */
        private int privateNotStaticAddTow(int num) {
            return num + ADD_NUM;
        }
    }

     2、单测类

    package com.shuimutong.demo.junit;
    
    import java.lang.reflect.Method;
    
    import org.junit.Assert;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.InjectMocks;
    import org.powermock.api.mockito.PowerMockito;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.PowerMockRunner;
    
    /**
     * 参照1:https://www.jianshu.com/p/0c2480b1709e
     * 参照2:https://www.cnblogs.com/ljw-bim/p/9391770.html
     * @ClassName:  NoRelayMethodTest   
     * @Description:(这里用一句话描述这个类的作用)   
     * @author: 水木桶
     * @date:   2019年10月26日 下午4:14:48     
     * @Copyright: 2019 [水木桶]  All rights reserved.
     */
    @RunWith(PowerMockRunner.class)
    @PrepareForTest({NoRelayMethod.class})
    public class NoRelayMethodTest {
        @InjectMocks
        private NoRelayMethod noRelayMethod;
        
        //不需要mock,可以去除上面3个注解
        @Test
        public void staticAddTwo() {
            int num = 3;
            int result = NoRelayMethod.staticAddTwo(num);
            Assert.assertTrue(result == (num + NoRelayMethod.ADD_NUM));
            
        }
        
        //不需要mock,可以去除上面3个注解
        @Test
        public void notStaticAddTwo() {
            int num = 1;
            NoRelayMethod noRelayMethod = new NoRelayMethod();
            int result = noRelayMethod.notStaticAddTwo(num);
            Assert.assertTrue(result == (num + NoRelayMethod.ADD_NUM));
        }
        
        //需要mock
        //mock私有方法
        @Test
        public void privateNotStaticAddTow() throws Exception {
            Method method = PowerMockito.method(NoRelayMethod.class, "privateNotStaticAddTow", int.class);
            int num = 3;
            Object res = method.invoke(noRelayMethod, 3);
            System.out.println(res);
            Assert.assertEquals(num + NoRelayMethod.ADD_NUM, res);
        }
    }

     3、备注

    staticAddTwo和notStaticAddTwo方法不需要RunWith、PrepareForTest、InjectMocks这3个注解。

    privateNotStaticAddTow涉及到私有方法,需要前面那3个注解。

    二、有依赖外部静态方法的单测

    1、待测试类

    package com.shuimutong.demo.junit;
    
    /**
     * 有依赖其他静态方法
     * @ClassName:  RelayMethod   
     * @Description:(这里用一句话描述这个类的作用)   
     * @author: 水木桶
     * @date:   2019年10月26日 下午3:26:01     
     * @Copyright: 2019 [水木桶]  All rights reserved.
     */
    public class RelayStaticMethod {
        public final static String DEFAULT_VAL = "defaultVal";
        public final static String SIGNED = "signed";
        
        /**
         * 依赖静态方法的
         * @param key
         * @return
         */
        public String checkAndCalc(String key) {
            String returnVal = null;
            String savedVal = RedisUtil.get(key);
            if(savedVal == null || savedVal.length() < 1) {
                returnVal = DEFAULT_VAL;
            } else {
                returnVal =  savedVal + "-" + SIGNED;
            }
            return returnVal;
        }
        
    }

    1-1、依赖外部类

    package com.shuimutong.demo.junit;
    
    import java.util.UUID;
    
    public class RedisUtil {
        private static boolean INIT_STATE = false;
        
        public static String get(String key) {
            if(INIT_STATE) {
                return UUID.randomUUID().toString();
            } else {
                throw new NullPointerException("资源未初始化");
            }
        }
        
    }

     2、单测类

    package com.shuimutong.demo.junit;
    
    import java.util.UUID;
    
    import org.junit.Assert;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.Mockito;
    import org.powermock.api.mockito.PowerMockito;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.PowerMockRunner;
    
    
    @RunWith(PowerMockRunner.class)
    //参考:https://www.jianshu.com/p/0c2480b1709e
    //1、如果想要对某个类的静态方法进行mock,则必须在PrepareForTest后面加上相应的类名, 比如此例的RedisUtil.class。
    @PrepareForTest({RedisUtil.class})
    public class RelayStaticMethodTest {
        /**
         * mock依赖的静态方法
         */
        @Test
        public void checkAndCalc() {
            String key1 = "jack";
            String key2 = "john";
            String val2 = UUID.randomUUID().toString();
            
            //2、在对该类的某个方法进行mock之前,还必须先对整个类进行mock
            PowerMockito.mockStatic(RedisUtil.class);
            PowerMockito.when(RedisUtil.get(Mockito.eq(key1))).thenReturn(null);
            PowerMockito.when(RedisUtil.get(Mockito.eq(key2))).thenReturn(val2);
            
            RelayStaticMethod relayMethod = new RelayStaticMethod();
            String res = relayMethod.checkAndCalc(key1);
            System.out.println("res:" + res);
            Assert.assertEquals(RelayStaticMethod.DEFAULT_VAL, res);
            
            res = relayMethod.checkAndCalc(key2);
            System.out.println("res:" + res);
            Assert.assertTrue(res.contains(RelayStaticMethod.SIGNED));
        }
        
    }

     2-1、运行结果

    res:defaultVal
    res:e76dc3b8-fcf5-42b8-9f79-1d308d137514-signed

     三、有依赖外部非静态方法的单测

    1、待测试类

    package com.shuimutong.demo.junit;
    
    /**
     * 参照1:https://www.jianshu.com/p/0c2480b1709e
     * 参照2:https://www.cnblogs.com/ljw-bim/p/9391770.html
     * @ClassName:  UserController   
     * @Description:(这里用一句话描述这个类的作用)   
     * @author: 水木桶
     * @date:   2019年10月26日 下午4:14:30     
     * @Copyright: 2019 [水木桶]  All rights reserved.
     */
    public class UserController {
        private UserService userService = new UserService();
        
        public User saveUser(String name) {
            return userService.save(name);
        }
    }

    1-1、依赖非静态类

    package com.shuimutong.demo.junit;
    
    public class UserService {
        public User save(String name) {
            System.out.println("UserService--save--name:" + name);
            User u = new User(name);
            u.setId((long)(Math.random() * 1000) + 2);
            return u;
        }
    }

     1-2、相关类User

    package com.shuimutong.demo.junit;
    
    public class User {
        private long id;
        private String name;
        
        public User(String name) {
            this.name = name;
        }
        public User() {
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
        @Override
        public String toString() {
            return "User [id=" + id + ", name=" + name + "]";
        }
    }

     2、单测类

    package com.shuimutong.demo.junit;
    
    import org.junit.Assert;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.Mockito;
    import org.powermock.api.mockito.PowerMockito;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.PowerMockRunner;
    
    /**
     * 参照1:https://www.jianshu.com/p/0c2480b1709e
     * 参照2:https://www.cnblogs.com/ljw-bim/p/9391770.html
     * @ClassName:  UserControllerTest   
     * @Description:(这里用一句话描述这个类的作用)   
     * @author: 水木桶
     * @date:   2019年10月26日 下午4:13:51     
     * @Copyright: 2019 [水木桶]  All rights reserved.
     */
    @RunWith(PowerMockRunner.class)
    @PrepareForTest({UserController.class})
    public class UserControllerTest {
        @Mock
        private UserService userService;
        @InjectMocks
        private UserController userController;
        
        @Test
        public void saveUser() {
            String name = "jack";
            //执行userService的实际方法
            PowerMockito.when(userService.save(Mockito.anyString())).thenCallRealMethod();
            User returnUser = userController.saveUser(name);
            System.out.println("returnUser:" + returnUser);
            Assert.assertTrue(returnUser.getId() > 1);
            
            long id = 1L;
            User u1 = new User(name);
            u1.setId(id);
            System.out.println("u1:" + u1);
            //mock userService的方法
            Mockito.when(userService.save(name)).thenReturn(u1);
            returnUser = userController.saveUser(name);
            //verify验证mock次数
            Mockito.verify(userService, Mockito.times(2)).save(name);
            Assert.assertEquals(id, returnUser.getId());
            Assert.assertEquals(u1, returnUser);
            System.out.println("returnUser:" + returnUser);
        }
    }

    2-1、执行结果

    UserService--save--name:jack
    returnUser:User [id=51, name=jack]
    u1:User [id=1, name=jack]
    UserService--save--name:jack
    returnUser:User [id=1, name=jack]

    四、相关环境

    1、依赖jar

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>2.10.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito2</artifactId>
        <version>2.0.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>2.0.2</version>
        <scope>test</scope>
    </dependency>

    2、源码地址

    https://gitee.com/simpleha/useDemo/tree/master/junit

  • 相关阅读:
    跳槽“六要”你懂吗?[转载]
    基于RFID 技术的仓储物流入库流程设计[转载]
    RFID:物流时代的新宠儿[转载]
    WEB界面设计五种特征[转]
    全国物流快递查询网址大全
    职员想跳槽,公司应检讨[转]
    商品条码管理办法 (2005)
    让总裁夜不成眠三件事[转]
    Google地图的配色问题(以及MapBar和51ditu)
    薪酬公开还是保密[转]
  • 原文地址:https://www.cnblogs.com/shuimutong/p/11743648.html
Copyright © 2011-2022 走看看