概述
mock简介
- py3已将mock集成到unittest库中
- 为的就是更好的进行单元测试
- 简单理解,模拟接口返回参数
- 通俗易懂,直接修改接口返回参数的值
- 官方文档:unittest.mock --- 模拟对象库 — Python 3.11.1 文档
mock作用
解决依赖问题,达到解耦作用
当我们测试某个目标接口(模块)时,该接口依赖其他接口,当被依赖的接口未开发完成时,可以用mock模拟被依赖接口,完成目标接口的测试
模拟复杂业务的接口
当我们测试某个目标接口(模块),该接口依赖一个非常复杂的接口时,可以用mock来模拟这个复杂的业务接口;也解决接口依赖一样的原理
单元测试
如果某个接口(模块)未开发完成时,又需要编写测试用例,则可以通过mock模拟该接口(模块)进行测试
前后端联调
前端开发的页面需要根据后端返回的不同状态码展示不同的页面,当后端接口未开发完成时,也可通过mock来模拟后端接口返回自己想要的数据
mock类解读
class Mock(spec=None,side_effect=None,return_value=DEFFAULT,name=None)
- secp:定义mock对象的属性值,可以是列表,字符串,甚至一个对象或者实例
- side_effect:可以用来抛出异常或者动态改变返回值,它必须是一个iterator(列表),它会覆盖return_value
- return_value:定义mock方法的返回值,它可以是一个值,可以是一个对象(如果存在side_effect参数那这个就没有用,也就是不能同时用)
- name:作为mock对象的一个标识,在print时可以看到
mock实际使用
一个未开发完成的功能如何测试?
1 def add(self, a, b):
2
"""两个数相加"""
3
pass
4
5
6 class TestSub(unittest.TestCase):
7
"""测试两个数相加用例"""
8
9
def test_sub(self):
10
# 创建一个mock对象 return_value代表mock一个数据
11
mock_add = mock.Mock(return_value=15)
12
# 将mock对象赋予给被测函数
13
add = mock_add
14
# 调用被测函数
15
result = add(5, 5)
16
# 断言实际结果和预期结果
17
self.assertEqual(result, 15)
一个完成开发的功能如何测试?
class SubClass(object):
def add(self, a, b):
"""两个数相加"""
return a + b
class TestSub(unittest.TestCase):
"""测试两个数相加用例"""
def test_add2(self):
# 初始化被测函数类实例
sub = SubClass()
# 创建一个mock对象 return_value代表mock一个数据
# 传递side_effect关键字参数, 会覆盖return_value参数值, 使用真实的add方法测试
sub.add = Mock(return_value=15, side_effect=sub.add)
# 调用被测函数
result = sub.add(5, 5)
# 断言实际结果和预期结果
self.assertEqual(result, 10)
side_effect:这里给的参数值是sub.add相当于add方法的地址,当我们调用add方法时就会调用真实的add方法
简单理解成:传递了side_effect参数且值为被测函数地址时,mock不会起作用;两者不可共存
另外,side_effect接受的是一个可迭代序列,当传递多个值时,每次调用mock时会返回不同的值;如下
1 mock_obj = mock.Mock(side_effect= [1,2,3])
2 print(mock_obj())
3 print(mock_obj())
4 print(mock_obj())
5 print(mock_obj())
6
7 # 输出
8 Traceback (most recent call last):
9 1
10
File "D:/MyThreading/mymock.py", line 37, in <module>
11 2
12
print(mock_obj())
13 3
14
File "C:Python36libunittestmock.py", line 939, in __call__
15
return _mock_self._mock_call(*args, **kwargs)
16
File "C:Python36libunittestmock.py", line 998, in _mock_call
17
result = next(effect)
18 StopIteration
存在依赖关系的功能如何测试?
1 # 支付类
2 class Payment:
3
4
def requestOutofSystem(self, card_num, amount):
5
'''
6
请求第三方外部支付接口,并返回响应码
7
:param card_num: 卡号
8
:param amount: 支付金额
9
:return: 返回状态码,200 代表支付成功,500 代表支付异常失败
10
'''
11
# 第三方支付接口请求地址(故意写错)
12
url = "http://third.payment.pay/"
13
# 请求参数
14
data = {"card_num": card_num, "amount": amount}
15
response = requests.post(url, data=data)
16
# 返回状态码
17
return response.status_code
18
19
def doPay(self, user_id, card_num, amount):
20
'''
21
支付
22
:param userId: 用户ID
23
:param card_num: 卡号
24
:param amount: 支付金额
25
:return:
26
'''
27
try:
28
# 调用第三方支付接口请求进行真实扣款
29
resp = self.requestOutofSystem(card_num, amount)
30
print('调用第三方支付接口返回结果:', resp)
31
except TimeoutError:
32
# 如果超时就重新调用一次
33
print('重试一次')
34
resp = self.requestOutofSystem(card_num, amount)
35
36
if resp == 200:
37
# 返回第三方支付成功,则进行系统里面的扣款并记录支付记录等操作
38
print("{0}支付{1}成功!!!进行扣款并记录支付记录".format(user_id, amount))
39
return 'success'
40
41
elif resp == 500:
42
# 返回第三方支付失败,则不进行扣款
43
print("{0}支付{1}失败!!不进行扣款!!!".format(user_id, amount))
44
return 'fail'
45
46 # 单元测试类
47 class payTest(unittest.TestCase):
48
49
def test_pay_success(self):
50
pay = Payment()
51
# 模拟第三方支付接口返回200
52
pay.requestOutofSystem = mock.Mock(return_value=200)
53
resp = pay.doPay(user_id=1, card_num='12345678', amount=100)
54
self.assertEqual('success', resp)
55
56
def test_pay_fail(self):
57
pay = Payment()
58
# 模拟第三方支付接口返回500
59
pay.requestOutofSystem = mock.Mock(return_value=500)
60
resp = pay.doPay(user_id=1, card_num='12345678', amount=100)
61
self.assertEqual('fail', resp)
62
63
def test_pay_time_success(self):
64
pay = Payment()
65
# 模拟第三方支付接口首次支付超时,重试第二次成功
66
pay.requestOutofSystem = mock.Mock(side_effect=[TimeoutError, 200])
67
resp = pay.doPay(user_id=1, card_num='12345678', amount=100)
68
self.assertEqual('success', resp)
69
70
def test_pay_time_fail(self):
71
pay = Payment()
72
# 模拟第三方支付接口首次支付超时,重试第二次失败
73
pay.requestOutofSystem = mock.Mock(side_effect=[TimeoutError, 500])
74
resp = pay.doPay(user_id=1, card_num='12345678', amount=100)
75
self.assertEqual('fail', resp)
也许有小伙伴会问,第三方支付都不能用,我们的测试结果是否是有效的呢?
通常在测试一个模块的时候,是可以认为其他模块的功能是正常的,只针对目标模块进行测试是没有任何问题的,所以说测试结果也是正确的
mock装饰器
一共两种格式
- @patch('module名字.方法名')
- @patch.object(类名, '方法名')
1 # 装饰类演示
2 from mock import Mock, patch
3
4
5 # 单独的相乘函数
6 def multiple(a, b):
7
return a * b
8
9
10 # 单独的捕获Exception函数
11 def is_error():
12
try:
13
os.mkdir("11")
14
return False
15
except Exception as e:
16
return True
17
18
19 # 计算类,包含add方法
20 class calculator(object):
21
def add(self, a, b):
22
return a + b
23
24
25 # 装饰类演示 - 单元测试类
26 class TestProducer(unittest.TestCase):
27
28
# case执行前
29
def setUp(self):
30
self.calculator = calculator()
31
32
# mock一个函数,注意也要指定module
33
@patch('mock_learn.multiple')
34
def test_multiple(self, mock_multiple):
35
mock_multiple.return_value = 3
36
self.assertEqual(multiple(8, 14), 3)
37
38
# mock一个类对象的方法
39
@patch.object(calculator, 'add')
40
def test_add(self, mock_add):
41
mock_add.return_value = 3
42
self.assertEqual(self.calculator.add(8, 14), 3)
43
44
# mock调用方法返回多个不同的值
45
@patch.object(calculator, 'add')
46
def test_effect(self, mock_add):
47
mock_add.side_effect = [1, 2, 3]
48
self.assertEqual(self.calculator.add(8, 14), 1)
49
self.assertEqual(self.calculator.add(8, 14), 2)
50
self.assertEqual(self.calculator.add(8, 14), 3)
51
52
# mock的函数抛出Exception
53
@patch('os.mkdir')
54
def test_exception(self, mkdir):
55
mkdir.side_effect = Exception
56
self.assertEqual(is_error(), True)
57
58
# mock多个函数,注意函数调用顺序
59
@patch.object(calculator, 'add')
60
@patch('mock_learn.multiple')
61
def test_more(self, mock_multiple, mock_add):
62
mock_add.return_value = 1
63
mock_multiple.return_value = 4
64
self.assertEqual(self.calculator.add(3, 3), 1)
65
self.assertEqual(multiple(3, 3), 4)
B站讲的最详细的Python接口自动化测试实战教程全集(实战最新版)
最后
以上就是无情鸭子为你收集整理的python接口自动化测试 - mock模块基本使用介绍的全部内容,希望文章能够帮你解决python接口自动化测试 - mock模块基本使用介绍所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复