精华内容
下载资源
问答
  • PowerMockito mock静态类

    千次阅读 2020-02-25 23:22:59
    PowerMockito mock静态类 1. Mock简介 一个大的项目中,类之间往往是相互依赖的,A类可能依赖B类,B类依赖C类。。。但是我们现在只想测试A类中的方法,如果不用Mock,就需要准备所有其他依赖类,并保证其他依赖类是...

    1. Mock简介

    一个大的项目中,类之间往往是相互依赖的,A类可能依赖B类,B类依赖C类。。。但是我们现在只想测试A类中的方法,如果不用Mock,就需要准备所有其他依赖类,并保证其他依赖类是正常工作的,非常麻烦。但是现在我们可以通过Mock造一个假的正确的B类结果出来,这样就将测试限制在对A类本身中,无需考虑其他依赖类。

    SpringBoot的单元测试,可以使用mockito进行mock。但是mockito无法mock static、final这样的方法,因此诞生了PowerMockito。

    2.PowerMockito依赖引入

    由于PowerMock是Mockito的增强,所以无需额外引用Mockito,而PowerMock依赖需要两个:

    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito2</artifactId>
        <version>RELEASE</version>
        <scope>test</scope>
    </dependency>
    

    3.与Mockito不同的地方

    PowerMockito里面封装了Mockito,所以使用PoweMockito时,也可以使用mockito的方法。@InjectMock和**@Mock**这些都是一样的,但是有一些地方需要改变下:

    (1)单元测试测试类上的@RunWith(SpringRunner.class)里面的SpringRunner换成PowerMockRunner

    注意,换成PowerMockRunner后,同一个类下的各个测试不再相互独立,它们公用一套环境,而不是每个测试起自己的环境,要注意是否存在对共有数据的修改。

    @RunWith(PowerMockRunner.class)
    

    (2)如果需要注入带有静态方法的类,类上加@PrepareForTest({XXX.class,XXX.class})

    @PrepareForTest(RedisUtil.class)
    

    注意:当需要mock系统类的静态方法的时候,必须加注解@PrepareForTest和@RunWith。注解里写的类不是系统类,而是调用系统类的类(一般是待测试类)。

    且写在@PrepareForTest 里的类不会被 Jacoco 收集到代码覆盖率!!!

    4.单测的写法

    (1)mock有返回值的静态方法

    mockStatic(XXX.class);
    when(XXX.staticMethod(anyString(), anyString())).thenReturn(XX);
    

    (2)mock void的静态方法

    mockStatic(XXX.class);
    doNothing().when(XXX.class, "voidStaticMethod", any(), any(), any());
    

    (3)mock私有方法

    mockPrivateClass = PowerMockito.spy(new MockPrivateClass());
    PowerMockito.when(mockPrivateClass, "privateFunc").thenReturn("test");
    

    注意:如果出现下面这个错误

    java.lang.LinkageError: loader constraint violation: loader (instance of org/powermock/core/classloader/javassist/JavassistMockClassLoader) previously initiated loading for a different type with name “javax/management/MBeanServer”

    只需要在测试类上加以下注解即可(在类上加,仅在某个test上加无效)

    @PowerMockIgnore("javax.management.*")
    

    5.实现部分方法Mock
    通过@mock标注的类的所有方法都会被mock,不会去执行实际的方法;而通过@InjectMock标注的类是一个注入mock对象的类,待测方法一般位于该类中,它的方法不会被mock掉。如果我们想mock一个@InjectMock类中的方法该怎么办?这时就可以使用部分方法mock。在Mockito和PowerMockito(这两个在这里是完全一样的)中有两种方式实现部分方法mock ,一种使用mock,一种使用spy。

    (1) mock实现
    使用mock,默认都是不执行实际方法,直接返回设定的返回值;但是如果要执行实际方法,则需要使用doCallRealMethod()或thenCallRealMethod():

    //假设TestService在全局是@InjectMock,这里单独重新声明为一个mock类
    TestService testService = Mockito.mock(TestService.class); //这个与@Mock作用一样,但是这个不会被注入到InjectMock类中
    //不调用实际方法,即不进入该方法中
    testService.testMethod(any());
    //2种调用实际方法的声明(Mockito和PowerMockito写法一样)
    doCallRealMethod().when(testService).testMethod(any());
    when(testService.testMethod(any())).thenCallRealMethod();
    //PowerMockito的另外两种写法
    PowerMockito.doCallRealMethod().when(testService, "testMethod", any());
    PowerMockito.when(testService, "testMethod", any()).thenCallRealMethod();
    

    (2)spy实现
    使用spy,thenReturn默认是执行实际方法的,只是返回值可以按照设定的进行返回;如果想要不执行实际方法,需要使用doReturn:

    TestService testService = Mockito.spy(new TestService());
    //2种会执行实际方法
    testService.testMethod(any());
    when(testService.testMethod(any())).thenReturn("hello");
    //不执行实际方法
    doReturn("hello").when(testService).testMethod(any()); //有返回值
    doNothing().when(testService).testMethod(any()); //无返回值
    

    6.部分方法mock时测试方法还引入了其他service时

    当我们通过上面的Mockito.mock(TestService.class)创造了一个新的testService时,该service默认是没有注入任何mock类的,如果测试方法中调用了其他service的方法,那么这个service就会报空指针的问题(因为没有注入)。为解决这个问题,就得重新Mock一个其他类,并通过 PowerMockito.field 注入进测试类中。

    PowerMockito.field本是用来mock私有变量的方法,但由于@Autowired标记的一般都是private变量,所以这里通过该方法进行注入。

    class TestService {
    	 @Autowierd
    	 private OtherService otherService;
     
     	 public String testMethod() {
     		......
     		String ret = otherService.otherMethod();
     		......
    	 }
    }
    
    TestService testService = PowerMockito.mock(TestService.class);
    OtherService otherService = PowerMockito.mock(OtherService.class);
    
    PowerMockito.when(testService.testMethod(any()).thenCallRealMethod();
    PowerMockito.field(TestService.class, "otherService").set(testService, otherService);
    PowerMockito.when(otherService.otherMathod(any())).thenReturn("xxx");
    

    总之:一般在测试某个类时,该类中被@Autowired注解的Bean都会在测试类中手动通过@Mock注入到InjectMock类中,因此不会出现空指针问题(即找不到该类)。但是通过 PowerMockito.mock() 创建的mock类中没有注入任何其他service,因此要警惕空指针情况(提前通过 PowerMockito.field 进行set)。

    7.注意 NullPointerException: can’t unbox null value 问题

    有时候测试时懒得造太多数据,给参数设为null,出现了NullPointerException: can’t unbox null value问题。这个问题不注意的话会以为是调用者为null,但其实是调用的方法中实参是null,形参是基本类型,导致出现拆箱问题。(其实就是不能出现 int a = null 这样的问题)

    展开全文
  • mock Context 我们写单元测试时,经常会用到context对象,但是直接使用context经常报空指针异常 正确的mock方式如下 ...2.在setUp方法中初始化 @Before public void setUp() throws Exception { MockitoAn...

    mock Context

    我们写单元测试时,经常会用到context对象,但是直接使用context经常报空指针异常
    正确的mock方式如下
    1.添加变量

    @Mock
    private Context mockApplicationContext;
    

    2.在setUp方法中初始化

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }
    

    3.在使用到context的地方灵活使用mockito的when方法
    比如我们用到context经常是因为String的关系,可以这样用

            when(mockApplicationContext.getString(R.string.filterOthers))
                    .thenReturn("Other");
    

    mock静态类的静态方法

    在我们测试时经常遇到静态类的静态方法无法通过测试,比如TextUtils
    其mock顺序如下
    1.测试类前声明

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({TextUtils.class, Xxx.class})
    public class Xxx{
    }
    

    2.初始化

        @Before
        public void setUp() throws Exception {
            PowerMockito.mockStatic(TextUtils.class);
        }
    

    3.在具体的测试方法灵活使用mockito的when方法
    比如

            when(TextUtils.isEmpty(price.getType()))
                    .thenReturn(price.getType().length() == 0);
    

    测试方法的顺序

    我们写测试方法时经常会遇到方法A调用B 方法B调用方法C的情况比如

    		if(flag1 == true){
    			methodA();
    		}else{
    			methodB(key);
    		}
    		
    		methodA(){
    			if(flag2 == true){
    				methodC();
    			}else{
    				methodD();
    			}
    		}
    		
    		methodB(key){
    			switch (key) {
    			case a:
    				methodE();
    				break;
    			case b:
    				methodF();
    				break;
    			case c:
    				methodG();
    				break;
    			default:
    				break;
    			}
    		}
    

    那么我们写测试方法的顺序从末端的方法写会容易一些,比如上面这个例子我们写的顺序是EFG CD AB(组内顺序不区分)
    当然如果写测试方法写的多了应该知道为方法A写测试方法时只要把两个分支都测了就OK了其实与方法内部调用的方法C和方法D没有关系。但是对于刚接触单元测试的我来说,这样写感觉上简单一些哈哈。

    展开全文
  • powermock mock 静态类,静态属性

    万次阅读 2017-09-15 11:10:28
    1.PowerMockito 版本问题 ...2.PowerMockito mock 静态类时初始化内存,以下顺序不能更改第二行先mock Objects.nonNull,再到第三行设置一把静态类  PowerMockito.mockStatic(Objects.class);  BDDMockito.given(O
    1.PowerMockito 版本问题
    

    https://stackoverflow.com/questions/26192929/unable-to-run-junit-test-with-powermockrunner

    <powermock.version>1.6.0</powermock.version>
    update to
    <powermock.version>1.6.1</powermock.version>

    2.PowerMockito mock 静态类时初始化内存,以下顺序不能更改第二行先mock Objects.nonNull,再到第三行设置一把静态类
            PowerMockito.mockStatic(Objects.class);
            BDDMockito.given(Objects.nonNull("META-INF/version.properties")).willReturn(false);
            Whitebox.setInternalState(AppVersion.class, "VERSION_FILE_LOCATION", "None exist");
            AppVersion appVersion = new AppVersion() {
            };

    测试类上面加注解
    @RunWith(PowerMockRunner.class)
    @PrepareForTest({AppVersion.class, Objects.class})

                <!-- mockito -->
                <dependency>
                    <groupId>org.mockito</groupId>
                    <artifactId>mockito-core</artifactId>
                    <version>${mockito.version}</version>
                </dependency>


                <dependency>
                    <groupId>org.powermock</groupId>
                    <artifactId>powermock-module-junit4</artifactId>
                    <version>${powermock.version}</version>
                </dependency>


                <dependency>
                    <groupId>org.powermock</groupId>
                    <artifactId>powermock-api-mockito</artifactId>
                    <version>${powermock.version}</version>
                    <exclusions>
                        <exclusion>
                            <groupId>org.mockito</groupId>
                            <artifactId>mockito-all</artifactId>
                        </exclusion>
                    </exclusions>
                </dependency>


                <dependency>
                    <groupId>org.easymock</groupId>
                    <artifactId>easymock</artifactId>
                    <version>${easymock.version}</version>
                </dependency>
    引用于:
    mock 方法
    https://stackoverflow.com/questions/21105403/mocking-static-methods-with-mockito
    mock 静态属性
    https://stackoverflow.com/questions/5385161/powermock-testing-set-static-field-of-class

    展开全文
  • PowerMockito Mock静态方法

    假设有类如下:

    public class MyClass {
    	public void publicMethod() {
    		......
    		String result = MyStaticClass.staticMethod();
    		......
    	}
    }
    
    public class MyStaticClass{
    	public static String staticMethod(String arg) {
    		......
    	}
    }
    

    对MyClass进行单元测试,测试publicMethod的时候可能需要对MyStaticClass.staticMethod进行mock,可以使用PowerMockito进行:

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({MyStaticClass.class})
    public class MyClassTest {
    	......
    	@Test
    	public void test() {
    		mockStatic(MyStaticClass.class);
    		spy(MyStaticClass.class);
    		when(MyStaticClass.staticMethod()).thenReturn("mockedResult");
            ......
            myClass .publicMethod();
    		......
    	}
    }
    
    展开全文
  • SpringBoot使用powermock来mock静态方法mock静态方法在测试类上添加 @RunWith在测试类上添加 @PrepareForTest 标注静态类测试代码里mock静态方法测试类添加加公有的无参数构造函数测试方法前面要加public测试方法用...
  • mock静态方法指引

    2021-03-15 13:05:43
    mock静态方法指引 mockito 在3.4.0版本开始支持mock static method 文档:https://wttech.blog/blog/2020/mocking-static-methods-made-possible-in-mockito-3.4.0/ 1. 升级Maven依赖 <!-- mockito --> <...
  • 可以用来Mock JAVA代码中的静态方法
  • 1.1、如何mock静态方法 1.2、mock很容易造成代码覆盖率的下降,如何提升代码覆盖率 二、准备工作 2.1、技术选型:powerMock 为何常见的Mockito不能mock静态方法? 因为Mockito使用继承的方式实现mock的,用...
  • 四.Android单元测试 PowerMock mock静态方法
  • SpringBoot单元测试之mock静态方法

    千次阅读 2020-08-26 19:44:43
    mockito库并不能 mock静态方法,需要依赖powermock才能对静态方法mock 2 如何使用powermock对静态方法mock 2.1 添加依赖 顺便添加对JsonPath的依赖 <?xml version="1.0" encoding="UTF-8"?> <pr
  • PowerMock Mock 静态方法

    千次阅读 2019-08-16 20:45:32
    – Start 假设我们有如下。 package demo01; import java.util.List; public class BusinessService { public List<... return BusinessUtil.getAllUser();...它调用如下的静态方法。 package de...
  • mockito库并不能 mock静态方法,需要依赖powermock这个库才能对静态方法mock 可以直接用这一组依赖 <dependency> ---!!!-这个版本依赖可以不加,下面三个必须要有 <groupId>org.mockito</...
  • Java 单元测试最趁手的 Mock 组件当属 Mockito,虽然它最初是基于继承来实现 Mock 的,所以对私有方法,私有属性,静态方法,final ,final方法,构造函数无能为力。于是有时不得不引入 JMockit 或 PowerMockit 来...
  • java mock 静态方法

    2020-12-08 18:23:00
    PowerMockito.mockStatic(RplTaskManager.class); PowerMockito.when(RplTaskManager.getTaskConfig(1)).thenReturn(taskConfig); //PowerMockito.when(RplTaskManager.getTaskConfig(any())).thenReturn...
  • Mockito为什么不能mock静态方法

    万次阅读 2015-11-11 13:58:46
    因为Mockito使用继承的方式实现mock的,用CGLIB生成mock对象代替真实的对象进行执行,为了mock实例的方法,你可以在subclass中覆盖它,而static方法是不能被子覆盖的,所以Mockito不能mock静态方法。 但...
  • How do I easily mock out a static method in Java?I'm using Spring 2.5 and JUnit 4.4@Servicepublic class SomeServiceImpl implements SomeService {public Object doSomething() {Logger.getLogger(this.class...
  • PowerMock mock final静态方法

    千次阅读 2020-08-09 21:19:06
    Junit + Powermock mock System.currentTimeMillis()方法,...被测代码是一个Util,其静态方法调用System.currentTimeMillis()方法: import java.util.concurrent.TimeUnit; public class TimeUtil { publi.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,894
精华内容 5,957
关键字:

mock静态类方法