原文:https://segmentfault.com/a/1190000008753754

一些常用的mock示例

先简单定义个类,方便举例:

class Person:
def __init__(self):
self.__age = 10 def get_fullname(self, first_name, last_name):
return first_name + ' ' + last_name def get_age(self):
return self.__age @staticmethod
def get_class_name():
return Person.__name__

这个类里有两个成员方法,一个有参数,一个无参数。还有一个静态方法


mock成员方法

1. 使用Mock类,返回固定值
class PersonTest(TestCase):
def test_should_get_age(self):
p = Person() # 不mock时,get_age应该返回10
self.assertEqual(p.get_age(), 10) # mock掉get_age方法,让它返回20
p.get_age = Mock(return_value=20)
self.assertEqual(p.get_age(), 20) def test_should_get_fullname(self):
p = Person() # mock掉get_fullname,让它返回'James Harden'
p.get_fullname = Mock(return_value='James Harden')
self.assertEqual(p.get_fullname(), 'James Harden')
2. 校验参数个数,再返回固定值

上面的例子你也许已经注意到了,调用p.get_fullname时没有给任何的参数,但是依然可以工作。
如果想校验参数需要用create_autospec模块方法替代Mock类。

class PersonTest(TestCase):
def test_should_get_fullname(self):
p = Person() p.get_fullname = create_autospec(p.get_fullname, return_value='James Harden') # 随便给两个参数,依然会返回mock的值
self.assertEqual(p.get_fullname('', ''), 'James Harden') # 如果参数个数不对,会报错TypeError: missing a required argument: 'last_name'
p.get_fullname('')
3. 使用side_effect, 依次返回指定值
class PersonTest(TestCase):
def test_should_get_age(self):
p = Person() p.get_age = Mock(side_effect=[10, 11, 12]) self.assertEqual(p.get_age(), 10)
self.assertEqual(p.get_age(), 11)
self.assertEqual(p.get_age(), 12)
4. 根据参数不同,返回不同的值
class PersonTest(TestCase):
def test_should_get_fullname(self):
p = Person() values = {('James', 'Harden'): 'James Harden', ('Tracy', 'Grady'): 'Tracy Grady'}
p.get_fullname = Mock(side_effect=lambda x, y: values[(x, y)]) self.assertEqual(p.get_fullname('James', 'Harden'), 'James Harden')
self.assertEqual(p.get_fullname('Tracy', 'Grady'), 'Tracy Grady')
5. 抛出异常
class PersonTest(TestCase):
def test_should_raise_exception(self):
p = Person() p.get_age = Mock(side_effect=TypeError('integer type'))
# 只要调就会抛出异常
self.assertRaises(TypeError, p.get_age)
6. 检验是否调用
class PersonTest(TestCase):
def test_should_validate_method_calling(self):
p.get_fullname = Mock(return_value='James Harden') # 没调用过
p.get_fullname.assert_not_called() # Python 3.5 p.get_fullname('', '') # 调用过任意次数
p.get_fullname.assert_called() # Python 3.6
# 只调用过一次, 不管参数
p.get_fullname.assert_called_once() # Python 3.6
# 只调用过一次,并且符合指定的参数
p.get_fullname.assert_called_once_with('', '') p.get_fullname('', '')
# 只要调用过即可,必须指定参数
p.get_fullname.assert_any_call('', '') # 重置mock,重置之后相当于没有调用过
p.get_fullname.reset_mock()
p.get_fullname.assert_not_called() # Mock对象里除了return_value, side_effect属性外,
# called表示是否调用过,call_count可以返回调用的次数
self.assertEqual(p.get_fullname.called, False)
self.assertEqual(p.get_fullname.call_count, 0) p.get_fullname('', '')
p.get_fullname('', '')
self.assertEqual(p.get_fullname.called, True)
self.assertEqual(p.get_fullname.call_count, 2)

mock静态方法

静态方法和模块方法需要使用patch来mock。

1. 在测试方法参数中得到Mock对象
class PersonTest(TestCase):
# 以字符串的形式列出静态方法的路径,在测试的参数里会自动得到一个Mock对象
@patch('your.package.module.Person.get_class_name')
def test_should_get_class_name(self, mock_get_class_name):
mock_get_class_name.return_value = 'Guy' self.assertEqual(Person.get_class_name(), 'Guy')
2. 在patch中设置Mock对象
class PersonTest(TestCase):
mock_get_class_name = Mock(return_value='Guy') # 在patch中给出定义好的Mock的对象,好处是定义好的对象可以复用
@patch('your.package.module.Person.get_class_name', mock_get_class_name)
def test_should_get_class_name(self):
self.assertEqual(Person.get_class_name(), 'Guy')
3. 使用patch.object
class PersonTest(TestCase):
mock_get_class_name = Mock(return_value='Guy') # 使用patch.object来mock,好处是Person类不是以字符串形式给出的
@patch.object(Person, 'get_class_name', mock_get_class_name)
def test_should_get_class_name(self, ):
self.assertEqual(Person.get_class_name(), 'Guy')
4. 使用with控制作用域
class PersonTest(TestCase):
# 作用域之外,依然返回真实值
def test_should_get_class_name(self, ):
mock_get_class_name = Mock(return_value='Guy')
with patch('your.package.module.Person.get_class_name', mock_get_class_name):
self.assertEqual(Person.get_class_name(), 'Guy') self.assertEqual(Person.get_class_name(), 'Person')

mock链式调用

在django里,我们经常需要mock数据库,而访问数据库时经常是链式调用,看个例子。

def get_person(name):
return Person.objects.filter(name=name).order_by('age')

有个模块方法,返回数据库中所有指定name的人员,并按age排序

mock掉整个数据库访问

@patch('your.package.module.Person.objects.filter')
def test_should_get_person(self, mock_filter):
# 先得到一个filter的Mock对象,再在return_value中设置一个Mock对象,此时不需要自己再创建
mock_filter.return_value.order_by.return_value = None self.assertIsNone(get_person())

Python中Mock的示例(转)的更多相关文章

  1. python中的tcp示例详解

    python中的tcp示例详解  目录 TCP简介 TCP介绍 TCP特点 TCP与UDP的不同点 udp通信模型 tcp客户端 tcp服务器 tcp注意点   TCP简介   TCP介绍 TCP协议 ...

  2. python中mock的使用

    什么是mock? mock在翻译过来有模拟的意思.这里要介绍的mock是辅助单元测试的一个模块.它允许您用模拟对象替换您的系统的部分,并对它们已使用的方式进行断言. 在Python2.x 中 mock ...

  3. Python中的 socket示例

    linux send与recv函数详解   1 #include <sys/socket.h> 2 ssize_t recv(int sockfd, void *buff, size_t ...

  4. [翻译]Mock 在 Python 中的使用介绍

    目录 Mock 在 Python 中的使用介绍 原文链接与说明 恐惧系统调用 一个简单的删除函数 使用 Mock 重构 潜在陷阱 向 'rm' 中加入验证 将文件删除作为服务 方法 1:模拟实例的方法 ...

  5. python中画散点图

    python中画散点图 示例代码: import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d impor ...

  6. Python中split()函数的用法及实际使用示例

    Python中split()函数,通常用于将字符串切片并转换为列表. 一.函数说明: split():语法:str.split(str="",num=string.count(st ...

  7. python中json的操作示例

    先上一段示例 # -*- coding: cp936 -*- import json #构造一个示例数据,并打印成易读样式 j = {} j["userName"]="a ...

  8. 利用Python中的mock库对Python代码进行模拟测试

    这篇文章主要介绍了利用Python中的mock库对Python代码进行模拟测试,mock库自从Python3.3依赖成为了Python的内置库,本文也等于介绍了该库的用法,需要的朋友可以参考下     ...

  9. 【转】利用Python中的mock库对Python代码进行模拟测试

    出处 https://www.toptal.com/python/an-introduction-to-mocking-in-python http://www.oschina.net/transla ...

随机推荐

  1. hdoj:2043

    #include <iostream> #include <string> using namespace std; bool judgeSize(string str) { ...

  2. Redis介绍以及安装(Linux)

    Redis介绍以及安装(Linux) redis是当前比较热门的NOSQL系统之一,它是一个key-value存储系统.和Memcached类似,但很大程度补偿了memcached的不足,它支持存储的 ...

  3. CALayer 知识:创建带阴影效果的圆角图片图层和创建自定义绘画内容图层

    效果如下: KMLayerDelegate.h #import <UIKit/UIKit.h> @interface KMLayerDelegate : NSObject @end KML ...

  4. 从vboot来看:virtualbox 和 vmware 虚拟化软件环境的兼容性(支持能力)的差距真是挺大的!

    仅仅就支持vboot启动来说:vwmare 完胜!! 熬了一周,(当前最新版本)用virtualbox 5.22 和 6.0 总是无法完成vboot的正常启动功能:不是蓝屏.就是死慢.要不就直接han ...

  5. linux 环境变量字符串的优先顺序

    /data/miniconda3dir/envs/mtfy/bin:$PATH 和$PATH:/data/miniconda3dir/envs/mtfy/bin 区别是非常大. 在linux中不同环境 ...

  6. [PHP] 07 - Json, XML and MySQL

    前言 [Node.js] 09 - Connect with Database 菜鸟JSON教程[内容不多] PHPSimpleXML[大概了解下即可] SQL语句需要复习一遍:http://www. ...

  7. [JS] Topic - why "strict mode" here

    Ref: Javascript 严格模式详解 使得Javascript在更严格的条件下运行: - 消除Javascript语法的一些不合理.不严谨之处,减少一些怪异行为; - 消除代码运行的一些不安全 ...

  8. 正整数序列Q中的每个元素都至少能被正整数a和b中的一个整除,现给定a和b,如何生成Q中的前几项

    思路分析:可以与归并排序联系起来,给定两个变量A.B,变量A轮着存放:a*1,a*2,a*3,……变量组B轮着存放:b*1,b*2,b*3,……有两个整数i.j,分别代表A.B第i.j次存放的值,每次 ...

  9. Linux驱动技术(三) _DMA编程

    DMA即Direct Memory Access,是一种允许外设直接存取内存数据而没有CPU参与的技术,当外设对于该块内存的读写完成之后,DMAC通过中断通知CPU,这种技术多用于对数据量和数据传输速 ...

  10. es7 class装饰器

    文档http://es6.ruanyifeng.com/#docs/decorator ts文档 https://www.tslang.cn/docs/handbook/decorators.html ...