Mockito框架里面的@Mock注解原理

简介: 一文看懂@Mock注解的底层的底层原理:@Mock注解的底层其实就是用cglib

@Mock注解就是其实就是用cglib的原理帮我们new了一个@Mock注解作用类的子类,什么意思呢,往下看

20190711141228183

首先是Company,此时hh方法返回值是”字符串”,

package com.one.util;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Company {
    private String name;

    public String hh(){
        return "字符串";
    }
}

User类,mm()的返回值就是Company类的hh()返回值

package com.one.util;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class User {
    private  Company company;

    private int age;


    public String mm(){
       return company.hh();
    }
}

然后UserTest类如下,此时可以看到下面的Company上面放了@Mock注解,他的作用就是帮我们生产一个Company类的子类(假如是CompanyZi),然后使用多态赋值给下面的company(就像这样Company company=new CompanyZi),而且这个ComanyZi类里面的hh()方法的返回值是null,为什么这样说呢,我们看下面的结果

package com.one.util;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.assertj.core.api.Assertions.catchThrowable;

@RunWith(MockitoJUnitRunner.class)
public class UserTest {

    @Mock
    private Company company;

    private User user;

    @Before
    public void setUp() {
        user = new User(company, 1);
    }

    @Test
    public void tt() {
        catchThrowable(() -> {
            String mm = user.mm();
            System.out.println(mm);
        });
    }

}

此时可以看到结果是null

20190711141344750

简单来说上面的代码可以变成下面这样

20190711141410267

首先是Company,此时hh方法返回值是”字符串”,

package com.one.util;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Company {
    private String name;

    public String hh(){
        return "字符串";
    }
}

User类,mm()的返回值就是Company类的hh()返回值

package com.one.util;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class User {
    private  Company company;

    private int age;


    public String mm(){
       return company.hh();
    }
}

然后UserTest类如下,此时下面的类ComapanyZi就相当于上面的被@Mock注解的company的最终被new的对象,只不过@Mock注解帮我做了下面的CompanyZi这个类,此时可以看到下面的ComapanyZi返回的是null

package com.one.util;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import static org.assertj.core.api.Assertions.catchThrowable;

@RunWith(JUnit4.class)
public class UserTest {

    class ComapanyZi extends Company{
        public ComapanyZi(String name) {
            super(name);
        }
        public String hh(){
            return null;
        }
    }
    private User user;

    @Test
    public void name() {
        user=new User(new ComapanyZi("zi"),1);
        Throwable throwable = catchThrowable(() -> {
            System.out.println(user.mm());
        });
    }
}

此时可以看到结果是null

20190711141524966

我们可以验证上面的结论

就是给@Mock注解的类添加一个final,然后在运行的时候就报错了

20190711141543906

Company类,此时可以看到Compan已经被final修改了

package com.one.util;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public final class Company {
    private String name;

    public String hh(){
        return "字符串";
    }
}

User类

package com.one.util;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class User {
    private  Company company;

    private int age;


    public String mm(){
       return company.hh();
    }
}

然后测试如下,然后运行下面的name方法,然后结果如下所示

package com.one.util;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;


@RunWith(MockitoJUnitRunner.class)
public class UserTest {

    @Mock
    private Company company;

    private User user;

    @Before
    public void setUp(){
        user = new User(company,1);
    }

    @Test
    public void name() {
        user.mm();
    }
}

此时可以看到报错了,说Company不能被final修改,者更好符号cglib的规则

20190711141632887

原文链接

目录
相关文章
|
XML 数据格式
TestNG学习-beanshell、注解转换和方法拦截器
TestNG学习-beanshell、注解转换和方法拦截器
|
Java Spring 容器
单测中如何mock用@Value注解注入的属性
单测中如何mock用@Value注解注入的属性
1003 0
|
监控 前端开发 JavaScript
Spring模块 | 拦截器如何实现
Spring根据官方文档实现拦截器
93 0
|
Java API 开发者
JSR 269插件化注解处理实践(以模拟Lombok自动生成getter/setter为例)
JSR 269是jdk1.6中引入的,在此之前,开发者只能在运行期对注解进行处理,而JSR 269允许开发这在编译期对注解进行处理,以此可以完成很多java不支持的特性,甚至创造新的语法糖。大名鼎鼎的lombok就是基于JSR 269来实现的。1. 原理介绍javac的编译过程如下图所示:可以看到JSR 269,也就是注解处理在编译产生抽象语法树AST之后,在此处插入一些逻辑,并且可以对AST进行
514 0
JSR 269插件化注解处理实践(以模拟Lombok自动生成getter/setter为例)
|
测试技术
Junit单元测试类、反射、注解
Junit单元测试类、反射、注解
132 0
|
Java 编译器
注解案例--简单的测试框架
注解案例--简单的测试框架
注解案例--简单的测试框架
|
Java 关系型数据库 MySQL
【SpringBoot 基础系列】接口上注解 AOP 拦截不到场景兼容实例演示
在 Java 的开发过程中,面向接口的编程可能是大家的常态,切面也是各位大佬使用 Spring 时,或多或少会使用的一项基本技能;结果这两个碰到一起,有意思的事情就发生了,接口方法上添加注解,面向注解的切面拦截,居然不生效 这就有点奇怪了啊,最开始遇到这个问题时,表示难以相信;事务注解也挺多是写在接口上的,好像也没有遇到这个问题(难道是也不生效,只是自己没有关注到?) 接下来我们好好瞅瞅,这到底是怎么个情况
483 0
【SpringBoot 基础系列】接口上注解 AOP 拦截不到场景兼容实例演示
|
XML 安全 Java
【框架】[Spring]纯Java的方式实现AOP切面(拦截)技术
【框架】[Spring]纯Java的方式实现AOP切面(拦截)技术
446 0
【框架】[Spring]纯Java的方式实现AOP切面(拦截)技术
|
测试技术 API
Mockito 一个优秀的 Mock 测试框架
Hello 大家好,我是阿粉,日常工作中很多时候我们都需要同事间的相互配合协作完成某些功能,所以我们经常会遇到服务或者应用内不同模块之间要互相依赖的场景。比如下面的场景,serviceA 中的 methodA() 方式依赖 serviceB 中的 methodB() 方法返回操作的结果。那如果我们要对自己的methodA() 方法进行编写单元测试,还需要等其他同事的methodB() 方法开发完成才行。那有没有什么办法我们可以跳过或者说模拟方法 B 的输出呢?这就引出了我们今天的主角 Mockito,一个优秀的 Mock 测试框架。
Mockito 一个优秀的 Mock 测试框架