IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 手写简单版的powermock,写着玩 -> 正文阅读

[Java知识库]手写简单版的powermock,写着玩

因为觉得powermock的运用cglib来修改字节码挺好玩的,所以这几天自己研究了下,还是那样,基于TDD来编写powermock,写这篇文章的目的是为了厘清自己的思路

首先powermock的核心就是when和thenReturn这俩东西,when的时候,其实就是打了个桩:

public static <T> OngoingStubbing<T> when(T methodCall) {
        //return Mockito.when(methodCall);
        return new OngoingStubbing<T>(methodCall);
    }

这个桩子OngoingStubbing,在thenReturn时也会用到:

public class OngoingStubbing<T> {


    //answer
    // add ans
    // add return
    //
    private final InvocationContainerImpl0 invocationContainerImpl = new InvocationContainerImpl0();


    private T method;

    public OngoingStubbing (T method) {
        this.method = method;
    }
    public OngoingStubbing<T> thenReturn(T var1) {
        invocationContainerImpl.addAnswer(new Return0(var1));
        return this;
    }
}

可以看到里面有个invocationContainerImpl,这个变量是用来干什么的呢? 其实就是为了处理thenReturn时的返回变量的,通过addAnswer方法,既然是这样,那么这些answer是在什么时候取出来的呢? 当然是在后面实际调用方法时,会取到这个Answer,所以是怎么取到的?

也是通过invocationContainerImpl的方法findAnswersForStubbing,那么findAnswersForStubbing是在什么时候被调用的呢,就是通过修改字节码来使他在callback时会被调用到,callback的实现,在powermock分为七种,我们在这里用的MethodInteceptor,一个简单的实现是:

package mockito;

import org.mockito.cglib.proxy.MethodInterceptor;
import org.mockito.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class MethodInterceptorImpl implements MethodInterceptor {

    public Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable {
        return "2";
    }
}

自己写的MockCreator用来使用这个字节码增强:

package mockito;

import org.mockito.cglib.proxy.Enhancer;

public class MockCreator {

    public static <T> T createMock(Class<T> type) {

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(type);
        // 设置回调方法 - 回调方法实现为 FixedValue (固定值) .
        enhancer.setCallback(new MethodInterceptorImpl());
        // 创建 SampleClass 的代理子类实例
        T proxy = (T) enhancer.create();
        return proxy;
    }
}

现在的一个比较简略的实现就是,我们在测试方法运行之前,把需要mock的东西mock住:

import mockito.MethodInterceptorImpl;
import mockito.PowerMockito;
import mockito.StaticClass;
import org.junit.Before;
import org.junit.Test;
import org.mockito.cglib.proxy.Enhancer;
import org.mockito.cglib.proxy.FixedValue;

import static mockito.MockCreator.createMock;
import static mockito.PowerMockito.*;
public class MockTest {


    StaticClass staticmethod;

    //把stati to mock method
    // return 时把
    //nongq inte zuolesha
    @Before
    public void setUp() throws Exception{
        staticmethod = createMock(StaticClass.class);
    }



    @Test
    public void test() {

        mockStatic(StaticClass.class);
        StaticClass sc = new StaticClass();
        when(sc.nmsl()).thenReturn("2");
        System.out.println(staticmethod.nmsl());
    }


}

但是这样的一个没有实现的点,就是thenReturn时的value没法传进MethodImpl去,所以现在最难的一步就是,如何把thenReturn("2")的"2"传进callback里面

扩展callbackilter,可以用来多次增强并且在指定环境使用指定的方法,可参考:

实战CGLib系列之proxy篇(二):回调过滤CallbackFilter_java风云的博客-CSDN博客

我们看powermock源码的话,其实thenReturn就是addAnswer,

public OngoingStubbing<T> thenReturn(T var1) {
        invocationContainerImpl.addAnswer(new Return0(var1));
        return this;
    }

所以其实就是我们要把invocationImpl传进MethodInteceptorImpl里面,那么powermock是通过mockHandlerImpl处理的:

现在就是不知道invocationImpl是啥时候传进去mockHandlerImpl的

应该是when的时候,我们会把invocationImpl注册进mockHandler里面,不是,when的时候会生成一个ongoingstub,然后这个stub给后面使用

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:26:14  更:2022-05-09 12:30:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:37:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码