栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

单元测试框架TestableMock快速入门(三):校验Mock调用

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

单元测试框架TestableMock快速入门(三):校验Mock调用

目录

一、概述

二、基本校验器

三、基本匹配器

四、空值匹配器

五、字符串匹配器

六、万能匹配器

七、使用示例


一、概述

在测试中,除了需要将某些含有外部依赖的方法替换为Mock,经常还会需要验证该方法被调用时的参数是否符合预期。

在TestableMock中提供了校验器(verifier)和匹配器(matcher)来实现这一功能。譬如:

@Test
public test_case() {
    int res = insToTest.methodToTest();
    verify("mockMethod").with(123, "abc");
}

这个用例会检查在执行被测方法methodToTest()时,名称是mockMethod的Mock方法是否有被调用过,且调用时收到的参数值是否为123和"abc"(假设被Mock的mockMethod方法有两个参数)。

除了这种简单校验以外,TestableMock当前已经支持了多种校验器,以及能够模糊匹配参数特征的匹配器。

二、基本校验器
  • with(Object... args) → 验证方法是否被指定参数调用过;
  • withInOrder(Object... args) → 如果指定方法被调用了多次,依据实际调用顺序依次匹配;
  • withTimes(int expectedCount) → 验证方法是否被调用过指定次数,忽略对调用参数的检查;
  • without(Object... args) → 验证方法从未被使用指定参数调用过;
  • times(int count) → 连在with()或withInOrder()方法之后使用,验证该方法被同样条件的参数调用过了指定次数;

三、基本匹配器
  • any() → 匹配任何值,包括Null
  • any(Class clazz) → 匹配任何指定类型或子类型的值
  • anyTypeOf(Class... classes) → 匹配在列表中的任意一种类型的值
  • anyString() → 匹配任何字符串
  • anyNumber() → 匹配任何数值(整数或浮点数)
  • anyBoolean() → 匹配任何布尔值
  • anyByte() → 匹配任何单字节类型的值
  • anyChar() → 匹配任何单字符类型的值
  • anyInt() → 匹配任何整数类型的值
  • anyLong() → 匹配任何长整数类型的值
  • anyFloat() → 匹配任何浮点数类型的值
  • anyDouble() → 匹配任何双精度浮点数类型的值
  • anyShort() → 匹配任何短整数类型的值
  • anyArray() → 匹配任何数组
  • anyArrayOf(Class clazz) → 匹配任何指定类型的数组
  • anyList() → 匹配任何列表
  • anyListOf(Class clazz) → 匹配任何指定类型的列表
  • anySet() → 匹配任何集合
  • anySetOf(Class clazz) → 匹配任何指定类型的集合
  • anyMap() → 匹配任何映射
  • anyMapOf(Class keyClass, Class valueClass) → 匹配任何指定类型的映射
  • anyCollection() → 匹配任何容器
  • anyCollectionOf(Class clazz) → 匹配任何指定类型的容器
  • anyIterable() → 匹配任何迭代器
  • anyIterableOf(Class clazz) → 匹配任何指定类型的迭代器
  • eq(Object obj) → 匹配与指定值相等的对象
  • refEq(Object obj) → 匹配指定对象(非值相等,而是就是同一个对象)

四、空值匹配器
  • isNull() → 匹配Null
  • notNull() → 匹配除Null以外的任何值
  • nullable(Class clazz) → 匹配空或指定类型的任何值

五、字符串匹配器
  • contains(String substring) → 匹配包含特定子串的字符串
  • matches(String regex) → 匹配符合指定正则表达式的字符串
  • endsWith(String suffix) → 匹配以指定子串结尾的字符串
  • startsWith(String prefix) → 匹配以指定子串开头的字符串

六、万能匹配器
  • any(MatchFunction matcher) → 匹配符合指定表达式的值

七、使用示例

【a】编写被测试类

package com.wsh.testable.mock.testablemockdemo;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;


public class DemoMatcher {

    
    private void methodToBeMocked() {
        // pretend to have some code here
    }

    
    private void methodToBeMocked(Object a1, Object a2) {
        // pretend to have some code here
    }

    
    private void methodToBeMocked(Object[] a) {
        // pretend to have some code here
    }

    public void callMethodWithoutArgument() {
        methodToBeMocked();
    }

    public void callMethodWithNumberArguments() {
        // named variable and lambda variable will be recorded as different type
        // should have them both in test case
        List floatList = new ArrayList<>();
        floatList.add(1.0F);
        floatList.add(2.0F);
        Long[] longArray = new Long[]{1L, 2L};
        methodToBeMocked(1, 2);
        methodToBeMocked(1L, 2.0);
        methodToBeMocked(new ArrayList(){{ add(1); }}, new HashSet(){{ add(1.0F); }});
        methodToBeMocked(1.0, new HashMap(2){{ put(1, 1.0F); }});
        methodToBeMocked(floatList, floatList);
        methodToBeMocked(longArray);
        methodToBeMocked(new Double[]{1.0, 2.0});
    }

    public void callMethodWithStringArgument() {
        methodToBeMocked("hello", "world");
        methodToBeMocked("testable", "mock");
        methodToBeMocked(new String[]{"demo"});
    }

    public void callMethodWithObjectArgument() {
        methodToBeMocked(new BlackBox("hello"), new BlackBox("world"));
        methodToBeMocked(new BlackBox("demo"), null);
        methodToBeMocked(null, new BlackBox("demo"));
    }

}

【b】编写测试类

package com.wsh.testable.mock.testablemockdemo;

import com.alibaba.testable.core.annotation.MockMethod;
import com.alibaba.testable.core.error.VerifyFailedError;
import org.junit.jupiter.api.Test;

import static com.alibaba.testable.core.matcher.InvokeMatcher.any;
import static com.alibaba.testable.core.matcher.InvokeMatcher.anyArray;
import static com.alibaba.testable.core.matcher.InvokeMatcher.anyArrayOf;
import static com.alibaba.testable.core.matcher.InvokeMatcher.anyInt;
import static com.alibaba.testable.core.matcher.InvokeMatcher.anyList;
import static com.alibaba.testable.core.matcher.InvokeMatcher.anyListOf;
import static com.alibaba.testable.core.matcher.InvokeMatcher.anyLong;
import static com.alibaba.testable.core.matcher.InvokeMatcher.anyMapOf;
import static com.alibaba.testable.core.matcher.InvokeMatcher.anyNumber;
import static com.alibaba.testable.core.matcher.InvokeMatcher.anySetOf;
import static com.alibaba.testable.core.matcher.InvokeMatcher.anyString;
import static com.alibaba.testable.core.matcher.InvokeMatcher.contains;
import static com.alibaba.testable.core.matcher.InvokeMatcher.endsWith;
import static com.alibaba.testable.core.matcher.InvokeMatcher.isNull;
import static com.alibaba.testable.core.matcher.InvokeMatcher.matches;
import static com.alibaba.testable.core.matcher.InvokeMatcher.notNull;
import static com.alibaba.testable.core.matcher.InvokeMatcher.nullable;
import static com.alibaba.testable.core.matcher.InvokeMatcher.startsWith;
import static com.alibaba.testable.core.matcher.InvokeVerifier.verify;
import static org.junit.jupiter.api.Assertions.fail;


class DemoMatcherTest {

    
    private DemoMatcher demoMatcher = new DemoMatcher();

    
    public static class Mock {
        
        @MockMethod(targetMethod = "methodToBeMocked")
        private void methodWithoutArgument(DemoMatcher self) {
        }

        
        @MockMethod(targetMethod = "methodToBeMocked")
        private void methodWithArguments(DemoMatcher self, Object a1, Object a2) {
        }

        
        @MockMethod(targetMethod = "methodToBeMocked")
        private void methodWithArrayArgument(DemoMatcher self, Object[] a) {
        }
    }

    
    @Test
    void should_match_no_argument() {
        //callMethodWithoutArgument()方法内部调用了methodToBeMocked()方法
        demoMatcher.callMethodWithoutArgument();
        //检查在执行被测方法callMethodWithoutArgument()时,名称是methodWithoutArgument的Mock方法是否有被调用过一次,并忽略对调用参数的检查
        verify("methodWithoutArgument").withTimes(1);
        demoMatcher.callMethodWithoutArgument();
        //检查在执行被测方法callMethodWithoutArgument()时,名称是methodWithoutArgument的Mock方法是否有被调用过两次,并忽略对调用参数的检查
        verify("methodWithoutArgument").withTimes(2);
    }

    
    @Test
    void should_match_number_arguments() {
        //callMethodWithNumberArguments()方法内部调用了methodToBeMocked()很多重载的方法
        demoMatcher.callMethodWithNumberArguments();
        //验证Mock方法methodWithArguments()从未被使用指定参数调用过
        verify("methodWithArguments").without(anyString(), 2);
        //withInOrder(Object... args) → 如果指定方法被调用了多次,依据实际调用顺序依次匹配
        verify("methodWithArguments").withInOrder(anyInt(), 2);
        verify("methodWithArguments").withInOrder(anyLong(), anyNumber());

        //验证Mock方法methodWithArguments()是否被指定参数调用过
        verify("methodWithArguments").with(1.0, anyMapOf(Integer.class, Float.class));
        verify("methodWithArguments").with(anyList(), anySetOf(Float.class));
        verify("methodWithArguments").with(anyList(), anyListOf(Float.class));

        //验证Mock方法methodWithArrayArgument()是否被指定参数调用过
        verify("methodWithArrayArgument").with(anyArrayOf(Long.class));
        verify("methodWithArrayArgument").with(anyArray());
    }

    
    @Test
    void should_match_string_arguments() {
        //注意callMethodWithStringArgument()在类DemoMatcher中的实现
        demoMatcher.callMethodWithStringArgument();
        //验证Mock方法methodWithArguments()是否被指定参数调用过,参数分别满足以"he"开头、以"ld"结尾
        verify("methodWithArguments").with(startsWith("he"), endsWith("ld"));
        //参数类型:包含"stab"、匹配"m.[cd]k"正则表达式
        verify("methodWithArguments").with(contains("stab"), matches("m.[cd]k"));
        //参数类型:String类型的数组
        verify("methodWithArrayArgument").with(anyArrayOf(String.class));
    }


    
    @Test
    void should_match_object_arguments() {
        demoMatcher.callMethodWithObjectArgument();
        verify("methodWithArguments").withInOrder(any(BlackBox.class), any(BlackBox.class));
        verify("methodWithArguments").withInOrder(nullable(BlackBox.class), nullable(BlackBox.class));
        verify("methodWithArguments").withInOrder(isNull(), notNull());
    }

    
    @Test
    void should_match_with_times() {
        demoMatcher.callMethodWithNumberArguments();
        verify("methodWithArguments").with(anyNumber(), any()).times(3);

        demoMatcher.callMethodWithNumberArguments();
        boolean gotError = false;
        try {
            verify("methodWithArguments").with(anyNumber(), any()).times(4);
        } catch (VerifyFailedError e) {
            gotError = true;
        }
        if (!gotError) {
            fail();
        }
    }

}

本案例来自官网, 笔者只是做一个学习总结。更详细使用介绍参考官网:TestableMock

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/269685.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号