powermockito经常会结合mockito使用,先说一下这2个的介绍:

1.mockito和powermockito的简介

mockito和powermockito是什么东西呢?他们有什么作用呢?

mocktio和powermockito都是mock的工具类,主要是java的类库,mock就是伪装的意思。

他们适用于单元测试中,对于单元测试来说,我们不希望依赖于第三方的组件,比如数据库、webservice等。在写单元测试的时候,我们如果遇到了这些需要依赖第三方的情况,我们可以使用mock的技术,伪造出来我们自己想要的结果。

对于java而言,mock的对象主要是java 方法和 java类。

下面我就介绍一下怎么使用mockito和powermockito去进行mock。

2.mockito和powermockito的区别

在我看来,powermockito是mockito的一种增强,他们的powermockito可以调用mockito的方法,但是对于mocktio不能mock的对象或者方法,我们可以使用powermockito来实现。

比如mockito不能用于static method, final method, 枚举类, private method,这些我们都可以用powermockito来实现,当powermockito和mockito结合使用的时候,我们需要考虑兼容性的问题。

两者的版本需要兼容

mockito powermockito
2.8.9+ 2.x
2.8.0-2.8.9 1.7.x
2.7.5 1.7.0rc4
2.4.0 1.7.0rc2
2.0.0-beta – 2.0.42-beta 1.6.5-1.7.0rc
1.10.8 – 1.10.x 1.6.2 – 2.0
1.9.5-rc1 – 1.9.5 1.5.0 – 1.5.6
1.9.0-rc1 & 1.9.0 1.4.10 – 1.4.12
1.8.5 1.3.9 – 1.4.9
1.8.4 1.3.7 & 1.3.8
1.8.3 1.3.6
1.8.1 & 1.8.2 1.3.5
1.8 1.3
1.7 1.2.5

ref:https://github.com/powermock/powermock/wiki/mockito

3.具体用法

本文实现实现需要构造的接口和需要返回值的接口

引入依赖

<dependencies>
	<dependency>
		<groupid>org.projectlombok</groupid>
		<artifactid>lombok</artifactid>
	</dependency>
	<dependency>
		<groupid>org.springframework</groupid>
		<artifactid>spring-context-support</artifactid>
	</dependency>
	<dependency>
		<groupid>org.springframework</groupid>
		<artifactid>spring-test</artifactid>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupid>junit</groupid>
		<artifactid>junit</artifactid>
		<version>4.12</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupid>org.mockito</groupid>
		<artifactid>mockito-all</artifactid>
		<version>2.0.2-beta</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupid>org.powermock</groupid>
		<artifactid>powermock-module-junit4</artifactid>
		<version>1.7.4</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupid>org.powermock</groupid>
		<artifactid>powermock-api-mockito</artifactid>
		<version>1.7.4</version>
		<scope>test</scope>
	</dependency>
</dependencies>

需要mock的类:

processdb.java

package com.github.mock.simple.vo; 
public class processdb {    
    public processdb(string ss){
        system.out.println(ss + " enter processdb ...");
    }
    
    public processdb(){
        system.out.println("enter processdb ...");
    }
    
    public void getresultofconnectdbnoreturn(string ss) {
        system.out.println(ss + " enter getresultofconnectdbnoreturn ...");
    }
    
    public string getresultofconnectdb() {
        return "haha, really went to the database";
    }
}
 

需要测试的类:

iuserservice.java

package com.github.mock.simple.user; 
public interface iuserservice { 
    public string testedmehtod(); 
}

userserviceimpl.java

package com.github.mock.simple.user.impl; 
import org.springframework.stereotype.service; 
import com.github.mock.simple.user.iuserservice;
import com.github.mock.simple.vo.processdb;
 
@service
public class userserviceimpl implements iuserservice {
 
    @override
    public string testedmehtod(){
        system.out.println("enter userserviceimpl testedmehtod ...");
        processdb processdb = new processdb("bb");
        processdb.getresultofconnectdbnoreturn("aa");
        return processdb.getresultofconnectdb();
    } 
}

bussinessservice.java

package com.github.mock.simple.user.impl; 
import com.github.mock.simple.vo.processdb; 
public class bussinessservice {
    public string testedmehtod() {
        system.out.println("enter bussinessservice testedmehtod ...");
        processdb processdb = new processdb("bb");
        processdb.getresultofconnectdbnoreturn("aa");
        return processdb.getresultofconnectdb();
    }
}

测试类:

mockspringsimpletest.java

package com.github.mock.simple.test; 
import java.text.messageformat; 
import org.junit.assert;
import org.junit.before;
import org.junit.test;
import org.junit.runner.runwith;
import org.mockito.injectmocks;
import org.mockito.mock;
import org.mockito.mockitoannotations;
import org.powermock.api.mockito.powermockito;
import org.powermock.core.classloader.annotations.preparefortest;
import org.powermock.modules.junit4.powermockrunner;
import org.powermock.modules.junit4.powermockrunnerdelegate;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.test.context.contextconfiguration;
import org.springframework.test.context.junit4.springjunit4classrunner;
 
import com.github.mock.simple.user.iuserservice;
import com.github.mock.simple.user.impl.bussinessservice;
import com.github.mock.simple.user.impl.userserviceimpl;
import com.github.mock.simple.vo.processdb;
 
@runwith(powermockrunner.class)
@powermockrunnerdelegate(springjunit4classrunner.class)//spring上下文
@preparefortest({bussinessservice.class,userserviceimpl.class})
@contextconfiguration(locations = {"classpath:applicationcontext-mock-inject.xml"})
public class mockspringsimpletest {
 
    //使用spring上下文
    @autowired
    iuserservice userservice;
 
    @mock
    processdb processdb;
    
    //不使用spring上下文时,使用该注解
    @injectmocks
    private bussinessservice bussinessservice;
 
    @before
    public void initmocks() throws exception {
        mockitoannotations.initmocks(this);
        //reflectiontestutils.setfield(userservice, "processdb", processdb);
        powermockito.whennew(processdb.class).witharguments("bb").thenreturn(processdb);
        // powermockito.whennew(processdb.class).withnoarguments().thenreturn(processdb);
    }
 
    @test
    public void mockconnectdb() {
        string aa = "haha, everything is fake"; 
        powermockito.when(processdb.getresultofconnectdb()).thenreturn(aa);
        powermockito.donothing().when(processdb).getresultofconnectdbnoreturn("aa");
        system.out.println(bussinessservice.testedmehtod());
        assert.assertequals("haha, everything is fake", bussinessservice.testedmehtod());
    }
 
    @test
    public void mockconnectdb2() {
        try {
            string aa = "haha, everything is fake";
            powermockito.when(processdb.getresultofconnectdb()).thenreturn(aa);
            powermockito.donothing().when(processdb).getresultofconnectdbnoreturn("aa");
            system.out.println(userservice.testedmehtod());
            assert.assertequals("haha, everything is fake", userservice.testedmehtod());
        } catch (exception ex) {
            system.out.println("--- getmessage ---");
            system.out.println(ex.getmessage());
            system.out.println();
            
            system.out.println("--- tostring ---");
            system.out.println(ex.tostring());
            system.out.println();
            
//            system.out.println("--- printstacktrace ---");
//            stringwriter stringwriter = new stringwriter();
//            printwriter printwriter = new printwriter(stringwriter);
//            ex.printstacktrace(printwriter);
//            system.out.println(stringwriter.tostring());
//            system.out.println();
            
            system.out.println("--- printstacktrace diy ---");
            system.out.println(ex.getclass().getname() + ": " + ex.getmessage());
            stringbuilder sbexception = new stringbuilder();
            for (stacktraceelement ele : ex.getstacktrace()) {
                sbexception.append(messageformat.format("\tat {0}.{1}({2}:{3})\n", 
                    ele.getclassname(), ele.getmethodname(), ele.getfilename(), ele.getlinenumber()));;
            }
            system.out.println(sbexception);            
            sbexception = null;
//            stringwriter = null;
//            printwriter = null;
        }
    } 
}

扫描注入xml

最后applicationcontext-mock-inject.xml

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemalocation="
 http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd  
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd"> 
    <context:component-scan base-package="com.github.mock.simple"/> 
</beans>

对于没有实现类,但又被依赖的接口,在applicationcontext-mock-inject.xml添加如下内容 (本文不需要):

<bean name="ixxservice" class="org.mockito.mockito" factory-method="mock">
    <constructor-arg value="com.github.mock.simple.api.ixxservice"/>
</bean>

同时在测试类里面添加下面的代码:

@mock
ixxservice ixxservice;

在 @before里面添加下面的代码

reflectiontestutils.setfield(userservice, "ixxservice", ixxservice);

测试结果

powermockito的使用技巧

当it中有些依赖组件无法正常集成,需要mock支持测试,可以使用power mockito。

特别注意:

当对一个对象进行powermockito,应该在prepare方法,统一mock这个对象。然后在其他方法,分别进行调用when,否则,多个方法内进行mock,会出错。

比如有个 service处于it case的底层,普通的mock根本mock不进去,但我们又不能为了集成测试,为这个testcase单独开一个口子,注入mock对象。power mockito强大的mock能力在这里可以用上。

比如:

我的mock对象impalaservice它在schmamessagehandler类里new出来的,则需要加上注解。

首先在test 类的开头,加上注解头部,头部类是mock对象所在类。

@runwith(powermockrunner.class)
@preparefortest({httpclient.class,schemamessagehandler.class})

其次:

pooledimpalaservice impalaservice = powermockito.mock(pooledimpalaservice.class);
powermockito.whennew(pooledimpalaservice.class).witharguments((configurationanyobject()).thenreturn(impalaservice);
donothing().when(impalaservice).createtable(anystring(),(schema) anyobject());

使用powermockito,注意在用any()参数时候,比如

donothing().when(impalaservice).createtable(anystring(),(schema) anyobject());

参数列表中,只要一个使用了any(),any****,则所有参数都要用any相关的参数,否则mock不成功。

总的来说,在it当中,只有你想mock一个对象,一定可以,比如你在a类中用到了b类,那么在preparefortest中增加a类的注解。

如下:

@preparefortest({a.class})然后,在it中 声明一个b类,b b = powermockito.mock(b.class);这时候,就可以指定b的方法的返回值,或 powermockit.donothing().when(b).方法名(),让该方法什么也不做。

最后,再讲a实例化。powermockit是讲究mock设置顺序的。一定要注意。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持www.887551.com。