Python测试框架unittest之mock系列(三)- 重置方法、create_autospec、装饰器/管理器、依赖测试
1、重置方法reset_mock:将mock对象恢复到测试之前的状态(相当于没有调用过)。1、创建Demo.py文件(创建被测试类:People类)。脚本代码:#!/usr/bin/env python# -*- coding: utf-8 -*-"""被测试类"""# People类里有两个成员方法(一个有参数,一个无参数)、一个静态方法classPeople:def__init__(self)
1、重置方法
reset_mock:将mock对象恢复到测试之前的状态(相当于没有调用过)。
1、创建Demo.py文件(创建被测试类:People类)。
脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
被测试类
"""
# People类里有两个成员方法(一个有参数,一个无参数)、一个静态方法
class People:
def __init__(self):
self.__age = 20
def name(self,firstName,lastName):
return firstName + ' ' + lastName
def age(self):
return self.__age
@staticmethod
def class_name():
return People.__name__
2、创建MockTest_reset_mock.py文件(创建PeopleTest测试类)。
脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
重置方法
"""
from method.Demo import People
from unittest import mock
import unittest
class PeopleTest(unittest.TestCase):
def test_name(self):
# 调用被测试类People()
p = People()
p.name = mock.Mock(return_value='Hello Mock')
p.name('a', 'b')
p.name.reset_mock()
p.name.assert_not_called()
if __name__ == '__main__':
unittest.main(verbosity=2)
3、执行MockTest_reset_mock.py文件,运行结果:
调用p.name()方法,之后用reset_mock重置mock,最后用assert_not_called验证p.name()方法从未被调用过,执行成功。
2、create_autospec
create_autospec:校验参数个数,再返回固定值;create_autospec方法替代Mock方法。
1、创建Demo.py文件(创建被测试类:People类)。
脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
被测试类
"""
# People类里有两个成员方法(一个有参数,一个无参数)、一个静态方法
class People:
def __init__(self):
self.__age = 20
def name(self,firstName,lastName):
return firstName + ' ' + lastName
def age(self):
return self.__age
@staticmethod
def class_name():
return People.__name__
2、创建MockTest_create_autospec.py文件(创建PeopleTest测试类)。
脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
create_autospec(校验参数个数,再返回固定值)
"""
from method.Demo import People
from unittest import mock
import unittest
class PeopleTest(unittest.TestCase):
def test_name(self):
# 调用被测试类People()
p = People()
p.name = mock.create_autospec(p.name, return_value='Hello Mock')
print(p.name('a','b'))
self.assertEqual(p.name('a','b'), 'Hello Mock')
print(p.name('a'))
if __name__ == '__main__':
unittest.main(verbosity=2)
3、执行MockTest_create_autospec.py文件,运行结果:
(1)如果想校验参数需要用create_autospec方法替代Mock方法。
(2)随便传两个参数('a','b'),依然会返回mock的值(Hello Mock)。
(3)如果参数个数不对(传一个参数'a'),则会报错(例如TypeError: missing a required argument: 'lastName')。
3、装饰器/上下文管理器
mock库提供了patch函数来简化mock对象对原对象的替换。patch可以作为装饰器或者上下文管理器使用,这意味着在装饰的函数和上下文管理器中,对应的类会被替换为mock对象。
创建Demo.py文件(创建被测试类:People类)。
脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
被测试类
"""
# People类里有两个成员方法(一个有参数,一个无参数)、一个静态方法
class People:
def __init__(self):
self.__age = 20
def name(self,firstName,lastName):
return firstName + ' ' + lastName
def age(self):
return self.__age
@staticmethod
def class_name():
return People.__name__
3.1、@patch
3.1.1、在测试方法参数中得到Mock对象
1、创建MockTest_patch1.py文件(创建PeopleTest测试类)。
脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
装饰器/上下文管理器:@patch(在测试方法参数中得到Mock对象)
"""
from method.Demo import People
from unittest.mock import patch
import unittest
class PeopleTest(unittest.TestCase):
@patch('method.Demo.People.class_name')
def test_class_name(self, mock_class_name):
mock_class_name.return_value = 'Hello Mock'
print(People.class_name())
if __name__ == '__main__':
unittest.main(verbosity=2)
2、执行MockTest_patch1.py文件,运行结果:
(1)@patch以字符串的形式列出静态方法的路径,在测试方法(test_class_name)的参数里会自动得到一个Mock对象(mock_class_name)。
(2)设置class_name静态方法返回值为Hello Mock。
(3)调用People.class_name()静态方法,返回预设值Hello Mock。
3.1.2、在patch中设置Mock对象
1、创建MockTest_patch2.py文件(创建PeopleTest测试类)。
脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
装饰器/上下文管理器:@patch(在patch中设置Mock对象)
"""
from method.Demo import People
from unittest import mock
from unittest.mock import patch
import unittest
class PeopleTest(unittest.TestCase):
mock_class_name = mock.Mock(return_value='Hello Mock')
@patch('method.Demo.People.class_name', mock_class_name)
def test_class_name(self):
print(People.class_name())
if __name__ == '__main__':
unittest.main(verbosity=2)
2、执行MockTest_patch2.py文件,运行结果:
(1)定义Mock对象,设置返回值为Hello Mock。
(2)在@patch中给出定义好的Mock的对象,好处是定义好的对象可以复用。
(3)调用People.class_name()静态方法,返回预设值Hello Mock。
3.2、@patch.object
1、创建MockTest_patch_object.py文件(创建PeopleTest测试类)。
脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
装饰器/上下文管理器:@patch.object
"""
from method.Demo import People
from unittest import mock
from unittest.mock import patch
import unittest
class PeopleTest(unittest.TestCase):
mock_class_name = mock.Mock(return_value='Hello Mock')
@patch.object(People, 'class_name', mock_class_name)
def test_class_name(self):
print(People.class_name())
if __name__ == '__main__':
unittest.main(verbosity=2)
2、执行MockTest_patch_object.py文件,运行结果:
(1)定义Mock对象,设置返回值为Hello Mock。
(2)使用@patch.object来mock,好处是People类不是以字符串形式给出的。
(3)调用People.class_name()静态方法,返回预设值Hello Mock。
3.3、with
1、创建MockTest_patch_with.py文件(创建PeopleTest测试类)。
脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
装饰器/上下文管理器:使用with控制作用域
"""
from method.Demo import People
from unittest import mock
from unittest.mock import patch
import unittest
class PeopleTest(unittest.TestCase):
def test_class_name(self):
mock_class_name = mock.Mock(return_value='Hello Mock')
with patch('method.Demo.People.class_name', mock_class_name):
print(People.class_name())
print(People.class_name())
if __name__ == '__main__':
unittest.main(verbosity=2)
2、执行MockTest_patch_with.py文件,运行结果:
(1)定义Mock对象,设置返回值为Hello Mock。
(2)使用with控制作用域,调用第一个People.class_name()静态方法(作用域内),返回预设值Hello Mock;调用第二个People.class_name()静态方法(作用域外),返回真实值People。
4、依赖测试
场景:我们要测试A模块,A模块依赖于B模块的调用。但是由于B模块的改变,导致了A模块返回结果的改变,以至于A模块测试用例失败。对于A模块,以及A模块的用例来说,并没有变化,不应失败才对。这个时候就要利用mock模拟掉影响A模块的部分(B模块),使A模块顺利执行测试用例并且成功。
一、创建Demo.py文件。
创建被测试函数(moduleA、moduleB)
脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
依赖测试:被测试函数
"""
def moduleA(x, y):
valueA = x + y
valueB = moduleB(x, y)
return (valueA,valueB)
def moduleB(x, y):
return x - y + 5
二、创建MockTest.py文件。
创建TestDemo测试类。
1、不使用mock
1.1、脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
依赖测试:测试类
"""
import unittest
from dependent import Demo
class TestDemo(unittest.TestCase):
def test_moduleA(self):
x = 5
y = 3
valueA, valueB = Demo.moduleA(x, y)
self.assertEqual(8, valueA)
self.assertEqual(7, valueB)
if __name__ == '__main__':
unittest.main(verbosity=2)
1.2、执行MockTest.py文件,运行结果:
(1)valueA返回8(5+3)。
(2)valueB返回7(5-3+5)。
2、使用mock
2.1、脚本代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
依赖测试:测试类
"""
import unittest
from dependent import Demo
from unittest.mock import patch
class TestDemo(unittest.TestCase):
@patch('dependent.Demo.moduleB')
def test_moduleA_mock(self, mock_moduleB):
x = 5
y = 3
mock_moduleB.return_value = 10
valueA, valueB = Demo.moduleA(x, y)
mock_moduleB.assert_called_once_with(5, 3)
self.assertEqual(8, valueA)
self.assertEqual(10, valueB)
if __name__ == '__main__':
unittest.main(verbosity=2)
2.2、执行MockTest.py文件,运行结果:
(1)在定义测试用例中,将Demo的moduleB()函数(对象)重命名为mock_moduleB对象。
(2)设置mock_moduleB(moduleB()函数)返回值为10。
(3)调用Demo.moduleA()函数,并得到valueA, valueB返回值。
(4)验证mock_moduleB被调用了一次,并且该调用使用了指定的参数(5, 3)。
(5)验证valueA,返回8(5+3)。
(6)验证valueB,返回10(moduleB()函数被设置返回值为10)。
如果您觉得文章还不错,请 点赞、分享、在看、收藏 一下,因为这将是我持续输出更多优质文章的最强动力!
如果文章对你有帮助,麻烦伸出可爱的小手点个赞,感谢您的支持,你的点赞是我持续更新的动力。在这里推荐一个我自己创建的软件测试交流群,QQ:642830685,群中机会不定期的分享软件测试资源和面试题,以及行业资讯,大家可以在群中积极交流问题呀。
更多推荐
所有评论(0)