java 测试工具 - org.mockito

2 篇文章 0 订阅
原理:
	1、扫描包含 @Mock 注解的字段,创建对象并进行设置
	2、扫描包含 @InjectMocks 注解的字段,并进行注入(执行注入的是mockito,不是spring)
	3、配置mock数据
		1、调用 @Mock 字段的方法,创建 stub --- 第一次调用
		2、设置mock数据到 stub
	4、执行调用
		1、调用 @Mock 字段的方法,由于stub有数据,就返回mock的数据 --- 第二次调用

 

package cn.java.demo.user.service;

import cn.java.demo.user.dao.entity.User;
import cn.java.demo.user.dao.mapper.UserMapper;
import cn.java.demo.user.service.impl.UserServiceFacadeImpl;
import cn.java.demo.user.service.impl.UserServiceImpl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * 多级嵌套依赖
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceUseMockitoTest {

    /**
     * 注入mocker对象(执行注入的是mockito,不是spring)
     */
    @InjectMocks
    private UserServiceFacadeImpl userServiceFacadeImpl;

    /**
     * 创建mocker对象
     */
    @Mock
    private UserService userService;

    /**
     * 注入mocker对象(执行注入的是mockito,不是spring)
     * <p>
     * 创建一个实例,使用用@Mock(或@Spy)注解创建的mock将被注入到用该实例中
     */
    @InjectMocks
    private UserServiceImpl userServiceImpl;

    /**
     * 创建mocker对象
     */
    @Mock
    private UserMapper userMapper;

    @Before
    public void setUp() {
        /*
            1、获取注解引擎
                1、创建 GLOBAL_CONFIGURATION,放入线程上下文
                    尝试加载 org.mockito.configuration.MockitoConfiguration 类,否则使用 org.mockito.configuration.DefaultMockitoConfiguration
                2、获取注解引擎
                    org.mockito.internal.configuration.InjectingAnnotationEngine

            2、使用注解引擎处理测试类
            {
                1、解析声明的mocker(解析标注@Mock注解的对象)
                {
                    org.mockito.internal.configuration.InjectingAnnotationEngine.process(...)
                    {
                        1、委托处理  @Mocks, @Captors 等注解
                            org.mockito.internal.configuration.DefaultAnnotationEngine.process(...)
                            {
                                1、扫描测试类(UserServiceUseMockitoTest)的字段
                                    for (Field field : fields)
                                    {
                                        1、获取处理结果;
                                            1、获取《字段注解》的处理器,并执行处理器
                                                如:@Mock 注解
                                                {
                                                    org.mockito.internal.configuration.MockAnnotationProcessor.process(...)
                                                    {
                                                        1、创建handler
                                                        {
                                                            mockHandler = org.mockito.internal.handler.InvocationNotifierHandler
                                                            {
                                                                mockHandler : org.mockito.internal.handler.NullResultGuardian
                                                                {
                                                                    delegate : org.mockito.internal.handler.MockHandlerImpl.MockHandlerImpl
                                                                    {
                                                                        mockSettings : org.mockito.internal.creation.settings.CreationSettings
                                                                        {
                                                                            typeToMock : cn.java.demo.user.dao.mapper.UserMapper,
                                                                            xxx : org.mockito.internal.creation.MockSettingsImpl
                                                                            {
                                                                                defaultAnswer : org.mockito.internal.stubbing.defaultanswers.GloballyConfiguredAnswer
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }

                                                        2、创建mocker
                                                        {
                                                            1、查找mocker创建器
                                                            {
                                                                PluginSwitch(插件切换器)
                                                                    1、查找类路径下 "mockito-extensions/org.mockito.plugins.PluginSwitch" 文件
                                                                    2、没查找到使用默认值:org.mockito.internal.configuration.plugins.DefaultPluginSwitch
                                                                mockMaker (mocker创建器)
                                                                    1、查找类路径下 "mockito-extensions/org.mockito.plugins.MockMaker" 文件
                                                                    2、没查找到使用默认值:org.mockito.internal.creation.cglib.CglibMockMaker
                                                            }

                                                            2、创建mocker
                                                            {
                                                                1、方法的拦截器
                                                                {
                                                                    org.mockito.internal.creation.cglib.MethodInterceptorFilter
                                                                    {
                                                                       handler : org.mockito.internal.handler.InvocationNotifierHandler
                                                                       mockSettings : org.mockito.internal.creation.settings.CreationSettings
                                                                    }
                                                                }

                                                                2、创建代理对象
                                                                {
                                                                    org.mockito.internal.creation.cglib.CglibMockMaker.createMock(settings, mockHandler);
                                                                    {
                                                                        使用 cglib.Enhancer 创建代理对象,并返回
                                                                        {
                                                                            1、在内存中生成《类的内容(byte)》
                                                                                byte[] b = strategy.generate(this);

                                                                            2、把《类的内容(byte)》 转成《class》
                                                                                String className = ClassNameReader.getClassName(new ClassReader(b));
                                                                                getClassNameCache(loader).add(className);
                                                                                gen = ReflectUtils.defineClass(className, b, loader);
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }

                                                如:@Captor 注解
                                                    org.mockito.internal.configuration.CaptorAnnotationProcessor.process(...)

                                        2、把处理《结果对象》作为值注入到《测试对象的字段(userMapper)》
                                        {
                                            // ...
                                        }
                                    }
                            }

                        2、自行处理 @Spies 注解
                            org.mockito.internal.configuration.SpyAnnotationEngine.process(...)
                    }
                }

                2、执行注入(解析标注 @InjectMocks 注解的对象)
                {
                    org.mockito.internal.configuration.InjectingAnnotationEngine.processInjectMocks()
                    {
                        1、扫描含有 @InjectMocks 注解的字段列表 fields
                        2、扫描含有 @Spy、@Mock 注解的字段列表 mocks
                        3、执行注入,迭代fields对象列表,注入mocks含有的对象
                        {
                            for (Field field : fields) {
                                injectionStrategies.process(field, fieldOwner, mocks);
                                {
                                    1、尝试《构造函数》注入
                                    {
                                        org.mockito.internal.configuration.injection.ConstructorInjection.process(...)
                                    }

                                    2、尝试《属性》注入
                                    {
                                        org.mockito.internal.configuration.injection.PropertyAndSetterInjection.process(...)
                                        {
                                            processInjection(...)
                                            {
                                                injectMockCandidates(...)
                                                {
                                                    1、获取非 static & final 属性
                                                        orderedInstanceFieldsFrom(awaitingInjectionClazz)
                                                    2、注入
                                                        1、按《类型》匹配
                                                            org.mockito.internal.configuration.injection.filter.TypeBasedCandidateFilter.filterCandidate(...)
                                                        2、按《字段名》匹配
                                                            org.mockito.internal.configuration.injection.filter.NameBasedCandidateFilter
                                                        3、创建 setter
                                                            org.mockito.internal.configuration.injection.filter.FinalMockCandidateFilter
                                                }
                                            }
                                        }
                                    }
                                }

                                postInjectionStrategies.process(field, fieldOwner, mocks);
                                {
                                    1、使用spy注入
                                    {
                                        org.mockito.internal.configuration.injection.SpyOnInjectedFieldsHandler.process(...)
                                    }
                                }
                            }
                        } // end 执行注入
                    }
                }
            }
         */
        MockitoAnnotations.initMocks(this); // 初始化Mock对象
    }

    @Test
    public void getById() {
        /*
            《1、mocker数据》
                1、调用代理对象 userMapper.getById(BDDMockito.anyLong())
                    1、调用 userMapper 代理对象,即执行:org.mockito.internal.handler.MockHandlerImpl.handle(...)
                    2、代理对象创建 OngoingStubbingImpl
                        mockingProgress.reportOngoingStubbing(ongoingStubbing);

                2、when()
                    1、获取 OngoingStubbing 对象
                        mockingProgress.pullOngoingStubbing()

                3、thenAnswer(...)
                    1、设置 OngoingStubbing 对象的属性

         */
        if (false) { // 方式1
            // 创建 stub
            userMapper.getById(BDDMockito.anyLong()); // 进行了一次调用

            // 配置 stub
            BDDMockito.when(null).thenAnswer((InvocationOnMock invocationOnMock) -> { // 模拟userMapper
                Long id = (Long) invocationOnMock.getArguments()[0];
                if (null == id) {
                    return null;
                } else if (Long.valueOf(1).equals(id)) {
                    return User.builder().
                            id(1L).
                            passWord("pwd1").
                            realName("realName1").
                            userName("userName1").
                            build();
                } else {
                    return null;
                }
            });
        } else { // 方式2
            BDDMockito.when(userMapper.getById(BDDMockito.anyLong())).thenAnswer((InvocationOnMock invocationOnMock) -> { // 模拟userMapper
                Long id = (Long) invocationOnMock.getArguments()[0];
                if (null == id) {
                    return null;
                } else if (Long.valueOf(1).equals(id)) {
                    return User.builder().
                            id(1L).
                            passWord("pwd1").
                            realName("realName1").
                            userName("userName1").
                            build();
                } else {
                    return null;
                }
            });
        }


        /*
            《2、执行 & 断言》
         */
        Assert.assertEquals("pwd1", userServiceImpl.getById(1L).getPassWord());
        System.out.println(userServiceImpl.getById(1L).getPassWord());

        // 1、mocker数据
        BDDMockito.when(userService.getById(BDDMockito.anyLong())).thenAnswer((InvocationOnMock invocationOnMock) -> { // 模拟userMapper
            Long id = (Long) invocationOnMock.getArguments()[0];
            return userServiceImpl.getById(id);
        });

        // 2、执行 & 断言
        System.out.println(userServiceFacadeImpl.getById(1L));
    }
}

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值