Python中unittest.mock.patch的功能与用法
unittest.mock.patch是Python标准库中unittest.mock模块提供的一个装饰器,用于在单元测试中模拟或替代某个对象或方法。它可以用来替换被测试代码中的任何对象,包括模块、类、实例的方法等,从而在测试中控制被替换对象的行为和返回值。
patch功能的用法如下:
1. 作为装饰器使用:
patch可以作为一个装饰器应用到单元测试的函数上,用于临时替换被测试函数中的某个对象。被替换的对象将被一个新的Mock对象替代。
下面是一个使用patch作为装饰器的例子:
from unittest import TestCase, mock
class MyTest(TestCase):
@mock.patch('module_name.class_name.method_name')
def test_my_method(self, mock_method):
# 测试代码
pass
2. 用于上下文管理:
patch也可以作为一个上下文管理器使用,用于临时替换被测试函数中的某个对象。被替换的对象将被一个新的Mock对象替代。
下面是一个使用patch作为上下文管理器的例子:
from unittest import TestCase, mock
class MyTest(TestCase):
def test_my_method(self):
with mock.patch('module_name.class_name.method_name') as mock_method:
# 测试代码
pass
3. 用于函数调用:
patch还可以直接用于函数调用,用于临时替换被测试函数中的某个对象。被替换的对象将被一个新的Mock对象替代,但是这个替换只在函数调用期间有效,函数调用之后对象将恢复原来的状态。
下面是一个使用patch进行函数调用的例子:
from unittest import TestCase, mock
class MyTest(TestCase):
def test_my_method(self):
with mock.patch('module_name.class_name.method_name') as mock_method:
# 函数调用代码...
mock_method.assert_called_once()
除了以上常用的用法之外,patch还支持其他一些选项和参数,如autospec、new等,用于控制被替换对象的行为。
下面举一个具体的例子来阐述patch的用法:
假设有一个用户管理系统,其中有一个User类,具有新增用户和获取用户信息的方法。现在需要对这些方法进行单元测试。
# user.py
class User:
def __init__(self, name):
self.name = name
def get_info(self):
return f"User name: {self.name}"
def add_user(name):
user = User(name)
return user
def get_user_info(user):
return user.get_info()
现在我们要对add_user函数和get_user_info函数进行单元测试,但是在单元测试中我们不希望实际去创建User对象和调用User对象的方法,而是希望使用Mock对象来替代User对象。
# test_user.py
from unittest import TestCase, mock
from user import add_user, get_user_info
class UserTest(TestCase):
@mock.patch('user.User') # 使用patch装饰器
def test_add_user(self, mock_user):
# 设置Mock对象的行为
mock_user_instance = mock_user.return_value
mock_user_instance.name = 'Mock User'
# 调用add_user函数
result = add_user('John Doe')
# 验证add_user函数的返回值和Mock对象的行为
self.assertEqual(result.name, 'Mock User')
mock_user.assert_called_once_with('John Doe')
mock_user_instance.get_info.assert_not_called()
def test_get_user_info(self):
with mock.patch('user.User') as mock_user: # 使用patch上下文管理器
# 设置Mock对象的行为
mock_user_instance = mock_user.return_value
mock_user_instance.get_info.return_value = 'Mock User Info'
# 创建一个Mock对象
mock_user_obj = mock.Mock()
# 调用get_user_info函数
result = get_user_info(mock_user_obj)
# 验证get_user_info函数的返回值和Mock对象的行为
self.assertEqual(result, 'Mock User Info')
mock_user_instance.get_info.assert_called_once()
mock_user.assert_called_once_with(mock_user_obj)
以上代码中,我们使用patch装饰器和patch上下文管理器分别对不同的函数进行mock。在 个测试中,我们使用patch装饰器对User类进行mock,并设定mock对象的行为,然后调用add_user函数并验证返回值和mock对象的行为。
在第二个测试中,我们使用patch上下文管理器对User类进行mock,并设定mock对象的行为,然后创建一个mock对象作为参数调用get_user_info函数,并验证返回值和mock对象的行为。
通过使用patch,我们可以对被测试代码中的对象进行替换,从而在测试中控制对象的行为和返回值,使得测试变得简单、可控和可靠。
