博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python第三方库系列之十九--python測试使用的mock库
阅读量:6590 次
发布时间:2019-06-24

本文共 3092 字,大约阅读时间需要 10 分钟。

一、为什么须要mock
        在写unittest的时候,假设系统中有非常多外部依赖,我们不须要也不希望把全部的部件都执行一遍。比方,要验证分享到微博的功能,假设每次測试的时候都要真实地把接口调用一遍,不仅效率低,制造非常多垃圾数据,还可能由于外部因素导致unittest失败。

对于有些耗时更久,或者无法简单创建測试环境的系统。真实的測试就显得更不必要。

我们仅仅须要知道代码依照预期运行,并调用了相关的外部接口。还是拿分享到微博这个功能做样例,分享部分的伪代码可能是这种:

def share():    """Share system generated message to weibo."""    msg = generate_msg()    weibo = get_weibo_client(user_id)    weibo.upload(msg)
        假设有一种方法,測试上面代码的时候可以执行全部的代码。可是并不实际执行weibo.upload(msg),并且还能知道每一个函数被调用了几次。每次被调用的參数,那我们測试用例就方便多了。

        python中mock就是在測试的时候用来模拟外部服务的。一般以下的场景会使用到mock:
            a.数据库操作:没有必要每一次都去读写数据库
            b.HTTP 请求:网络操作非常耗时,測试的时候还要依赖外部的服务
            c.外部命令:运行系统命令,比方文件操作,进程操作等等。
二、mock的基本原理
上面也提到过。mock是替换代码中外部的服务。由于python是动态语言,一切都是对象,所以在运行之前把实例、方法、函数和变量替换掉。比方:

>>> import os>>> def myremove(filename):>>>     return filename>>> os.remove = myremove
>>> print os.remove('test-file')test-file
        上面的样例是最简单的说明,假设把myremove改动成Mock类。然后这个类里面在调用的时候(复写 __call__)可以依据传进来的參数决定它的行为。还能记录每一次调用,你就大致了解 Mock 做了什么。
三、mock的使用
(1)怎么 mock 一个函数?
from mock import MockmyMethod = Mock()myMethod.return_value = 3myMethod(1, 'a', foo='bar')myMethod.assert_called_with(1, 'a', foo='bar')    # TruemyMethod()myMethod.call_count                               # 2
        想要mock出一个函数。直接使用mock.Mock()实例。你能够在初始化的时候设定返回值myMethod = Mock(return_value=3)。也能够通过myMethod.return_value的属性来设置。
        除了return_value,你还能够mock side_effect,side_effect是一个函数或者异常。在mock的对象被调用的时候会被用相同的參数调用。
myMethod = Mock(side_effect=KeyError('whatever'))myMethod()Traceback (most recent call last): ...KeyError: 'whatever'
        上面的样例就是模拟一个异常,假设side_effect是函数的话,这个函数就会被调用,能够用来动态地生成返回值。

以下的样例mock一个能够返回输入字符串长度的函数。

def side_effect(str):    return len(str)myMethod = Mock(side_effect=side_effect)myMethod('sd')              # 2
在unittest的时候。mock还提供了以下几种assert语句:
assert_any_call
assert_called_once_with
assert_called_with

assert_has_calls

(2)怎么 mock 一个类的方法?

要想mock一个类中的某个方法,能够使用mock提供的patch方法:
import mockimport Module1@mock.patch.object(Module1.Class1, 'some_method')def test(mock_method):    mock_method.return_value = 3    mock_method.side_effect = some_side_effect    m = Module1.Class1()    m.some_method(*args, **kwargs)    assert m.some_method is mock_method    m.some_method.assert_called_with(*args, **kwargs)

(3)怎么 mock 一个类?

        有时候须要模拟一个函数或者类的行为。包含它全部的属性和方法,假设手动去一个个加入,实在低效并且easy出错。mock提供了autospec的功能。依据提供的模板类生成一个mock实例。

以下是mock一个函数的样例。

import mockdef myFunc(a, b, c):    pass>>> mock_func = mock.create_autospec(myFunc, return_value=3)>>> mock_func(1,2,3)>>> mock_func.assert_called_with(1,2,3)>>> mock_func('a string')Traceback (most recent call last): ...TypeError: 
() takes exactly 3 arguments (1 given)
mock 一个类和这个同样:
>>> mock_class = mock.create_autospec(myClass)

(4)平时的使用方法

        这里用返回值等于3,来模拟requests.post网络交互的返回值。省去了真实的网络交互。当然。也能够用一个方法返回值来代替3这个返回值。

import jsonimport mockfrom django.test import TestCaseclass ApiTest(TestCase):    @mock.patch('apps.agent.requests.post')    def test(self, mock_method):        mock_method.return_value = 3        mock_method.side_effect = some_side_effect        res = self.client.post('/url/to/post')        r = json.loads(res.content)        self.assertEqual(0, r['retval'])

转载地址:http://eqhno.baihongyu.com/

你可能感兴趣的文章
优雅地减少redux请求样板代码
查看>>
Iterables和迭代器
查看>>
ElementUI文档中忽略的内容补充
查看>>
node 进程管理
查看>>
Swift基础语法学习-4.Bool类型
查看>>
浅谈混合应用的演进
查看>>
死磕Android_App 启动过程(含 Activity 启动过程)
查看>>
inotify实时同步工具理论和实战
查看>>
SQL SERVER 2008数据库管理与维护总结
查看>>
nginx web服务理论与实战
查看>>
golang RWMutex读写互斥锁源码分析
查看>>
Tinker + Bugly + Jenkins 爬坑之路
查看>>
如何快速入手 Shell 脚本编程
查看>>
getElement四种方法返回的不同
查看>>
SpringBoot使用@Asyn注解注意事项
查看>>
「docker实战篇」python的docker爬虫技术-在linux下mitmproxy介绍和安装(四)
查看>>
python爬取公众号,用最简单的方式爬虫
查看>>
节流函数和防抖函数
查看>>
使用HanLP增强Elasticsearch分词功能
查看>>
iOS 协议 委托 代理 delegate
查看>>