前言
进行接口测试时,可能有些接口逻辑未实现或者不满足要求,我们需要先调试case
的逻辑,此时可能就需要mock
了。那在pytest
中该如何进行mock
呢?带着这个疑问我们一起探索。
pytest-mock是啥?
pytest-mock是一个pytest的插件,安装即可使用。它提供了一个名为mocker的fixture,仅在当前测试function或method生效,而不用自行包装。
首先,我们需要安装pytest-mock库。可以使用pip命令来安装:
pip install pytest-mock
基本用法
模拟函数的返回值
有时我们需要模拟一个函数的返回值,以便更好地控制测试场景。pytest-mock可以通过mocker
夹具实现这一点。以下是一个示例:
ini
# 测试函数
def test_function(mocker):
# 模拟一个函数的返回值
mocker.patch('module.function', return_value=42)
result = module.function()
assert result == 42
在上面的示例中,我们使用mocker.patch
方法模拟了module.function
函数的返回值为42。然后,我们调用该函数,并断言返回的结果是否为42。
模拟函数的行为
有时我们需要模拟一个函数的行为,例如抛出异常或调用其他函数。pytest-mock提供了side_effect
参数来实现这一点。以下是一个示例:
scss
# 测试函数
def test_function(mocker):
# 模拟一个函数的行为,抛出异常
mocker.patch('module.function', side_effect=Exception('mocked error'))
with pytest.raises(Exception):
module.function()
在上面的示例中,我们使用mocker.patch
方法模拟了module.function
函数抛出异常。然后,我们使用pytest.raises
上下文管理器来捕获预期的异常。
模拟对象的属性
除了模拟函数的返回值和行为,pytest-mock还可以模拟对象的属性。以下是一个示例:
ini
# 测试函数
def test_function(mocker):
# 创建一个模拟对象
obj = mocker.MagicMock()
# 设置模拟对象的属性
obj.attribute = 10
assert obj.attribute == 10
在上面的示例中,我们使用mocker.MagicMock
创建了一个模拟对象,并通过设置obj.attribute
属性为10来模拟对象的属性。然后,我们断言该属性的值是否为10。
场景案例
一个简单的计算器类Calculator
,该类提供了加法和乘法运算的方法。我们将使用pytest-mock来模拟依赖项并针对这个模块编写单元测试。
test_demo.py
python
class Calculator:
def add(self, x, y):
pass
def multiply(self, x, y):
pass
# 测试计算器类的加法运算
def test_addition(mocker):
# 创建一个模拟对象
calculator = Calculator()
# 模拟add方法的行为
mocker.patch.object(calculator, 'add', return_value=5)
# 调用add方法
result = calculator.add(2, 3)
# 断言结果是否为模拟的返回值
assert result == 5
# 测试计算器类的乘法运算
def test_multiplication(mocker):
# 创建一个模拟对象
calculator = Calculator()
# 模拟multiply方法的行为
mocker.patch.object(calculator, 'multiply', side_effect=lambda x, y: x * y)
# 调用multiply方法
result = calculator.multiply(2, 3)
# 断言结果是否为模拟的返回值
assert result == 6
在上述代码中,我们定义了两个测试函数test_addition
和test_multiplication
,分别测试了计算器类的加法运算和乘法运算。
对于测试加法运算的函数test_addition
,我们创建了一个名为calculator
的模拟对象,并使用mocker.patch.object
方法模拟了calculator.add
方法的返回值为5。然后,我们调用calculator.add(2, 3)
进行加法运算,并使用断言验证结果是否为模拟的返回值。
对于测试乘法运算的函数test_multiplication
,我们也创建了一个名为calculator
的模拟对象,并使用mocker.patch.object
方法模拟了calculator.multiply
方法的行为,即通过lambda函数实现了真实的乘法运算。然后,我们调用calculator.multiply(2, 3)
进行乘法运算,并使用断言验证结果是否正确。
运行测试: 执行以下命令来运行测试:
arduino
pytest -s -v test_demo.py::test_addition
执行之后会输出PASSED
,我们如果改动mock值mocker.patch.object(calculator, 'add', return_value=51)
,再次执行命令,会输出如下结果:
markdown
FAILED
=============================================================== FAILURES ===============================================================
____________________________________________________________ test_addition _____________________________________________________________
mocker = <pytest_mock.plugin.MockerFixture object at 0x11140a250>
def test_addition(mocker):
# 创建一个模拟对象
calculator = Calculator()
# 模拟add方法的行为
mocker.patch.object(calculator, 'add', return_value=51)
# 调用add方法
result = calculator.add(2, 3)
# 断言结果是否为模拟的返回值
> assert result == 5
E assert 51 == 5
test_dir/test_demo.py:24: AssertionError
相信到这里你应该已经掌握的它的用法。
运行机制
pytest-mock的运行机制如下:
- pytest-mock的mock功能,可以用来修改、替换或者移除原有的Python对象。
- 在测试函数中,如果需要mock某个函数或对象的行为,可以在测试函数参数中添加
mocker
参数,mocker是一个Fixture对象,可以用来创建并管理mock对象。 - 通过调用mocker.patch()方法,可以对要mock的函数或对象进行替换或者修改。例如,在测试函数中,调用mocker.patch()方法,并传入要mock的函数名以及mock后的返回值,就可以将该函数的实际调用结果替换成mock的返回值,以便测试函数的正确性。
最后
本文介绍了pytest-mock的基本用法,包括模拟函数的返回值和行为,以及模拟对象的属性。我们还通过一个案例说明展示了如何使用pytest-mock进行单元测试。掌握了这些基本用法,可以更轻松地编写可靠的单元测试。