欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Mock、Powermock使用汇总

程序员文章站 2022-11-07 12:02:54
mock、powermock使用学习,mock静态方法、私有方法。 ......

背景

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

主要参考: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