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

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

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

首先是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

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

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

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

首先是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

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

我们可以验证上面的结论

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

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

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的规则

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

原文链接

上一篇:如何使用事务码SMICM分析ABAP代码发起的HTTP请求的错误


下一篇:分布式唯一ID系列(5)——Twitter的雪法算法Snowflake适合做分布式ID吗