python mock支付_python第三方库系列之十九--python测试使用的mock库

1、为何须要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.外部命令:执行系统命令,好比文件操做,进程操做等等。

2、mock的基本原理

上面也提到过,mock是替换代码中外部的服务。由于python是动态语言,一切都是对象,因此在执行以前把实例、方法、函数和变量替换掉。好比:

>>> import os

>>> def myremove(filename):

>>> return filename

>>> os.remove = myremove

>>> print os.remove('test-file')

test-file        上面的例子是最简单的说明,若是把myremove修改为Mock类,而后这个类里面在调用的时候(复写 __call__)可以根据传进来的参数决定它的行为,还能记录每一次调用,你就大体了解 Mock 作了什么。

3、mock的使用

(1)怎么 mock 一个函数?

from mock import Mock

myMethod = Mock()

myMethod.return_value = 3

myMethod(1, 'a', foo='bar')

myMethod.assert_called_with(1, 'a', foo='bar') # True

myMethod()

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_callspython

(2)怎么 mock 一个类的方法?数据库 要想mock一个类中的某个方法,可使用mock提供的patch方法:

import mock

import 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 一个类?django         有时候须要模拟一个函数或者类的行为,包括它全部的属性和方法,若是手动去一个个添加,实在低效并且容易出错。mock提供了autospec的功能,根据提供的模板类生成一个mock实例。 下面是mock一个函数的例子。

import mock

def 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)平时的用法json

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

import json

import mock

from django.test import TestCase

class 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'])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值