[英]What is the difference between mocking with @patch() with and without side_effect?
I have a script.py
file:我有一个
script.py
文件:
# in script.py
def my_basic_function(value, c):
return c(value).words()
class BasicClass:
def __init__(self, val):
self.val = val
def words():
return self.val
and a test.py
file:和一个
test.py
文件:
# in test.py
from mock import patch
from script import my_basic_function, BasicClass
def third_function(self,):
return "not {}".format(self.val)
def fourth_function():
return "not ponies"
def init_mock(self, val):
self.val = val
@patch('script.BasicClass.words', third_function)
@patch('script.BasicClass.__init__', init_mock)
def test_my_basic_function():
assert my_basic_function("ponies", BasicClass) == "not ponies"
that I can run using pytest test.py
from the command line successfully.我可以成功地从命令行使用
pytest test.py
运行。
If I want to use side_effect
in my @patch
, I have to do things a little differently:如果我想在我的
@patch
使用side_effect
,我必须做一些不同的事情:
@patch('script.BasicClass.words', side_effect = fourth_function)
@patch('script.BasicClass.__init__', init_mock)
def test_my_basic_function(amock):
assert my_basic_function("ponies", BasicClass) == "not ponies"
ie, I have to:即,我必须:
test_my_basic_function
that I never use.test_my_basic_function
添加一个我从未使用过的参数。fourth_function
rather than third_function
, as I cannot use any class instance variables.fourth_function
而不是third_function
,因为我不能使用任何类实例变量。 What is the difference between patching in these two ways?这两种方式打补丁有什么区别?
You don't need patches for what you are doing ( Example A ).您不需要为您正在做的事情打补丁(示例 A )。 You are passing in the parameter c which you know to be the class of BasicClass so no need for a patch.
您正在传入参数 c,您知道它是 BasicClass 的类,因此不需要补丁。 You would need a patch if you introduced a function call or object initialization in the function you are testing where you don't want to actually take place.
如果您在正在测试的函数中引入了函数调用或对象初始化,而您不想实际发生,则需要一个补丁。
When using @patch
we should use the kwarg side_effect
to simulate the raising of exceptions, not calling other functions.使用
@patch
我们应该使用 kwarg side_effect
来模拟引发异常,而不是调用其他函数。 If we want to simulate the return value of a function then use kwarg return_value
.如果我们想模拟函数的返回值,请使用 kwarg
return_value
。 If we just want to mock a function, then we just use @patch
without any kwargs.如果我们只想模拟一个函数,那么我们只需使用
@patch
而不使用任何 kwargs。 When we use patches as a decorator we need to pass them into the function.当我们使用补丁作为装饰器时,我们需要将它们传递给函数。 It is true they can be unused but we should use them with mock functions such as
assert_called_once
or assert_called_once_with
to ensure your patches are working as expected.的确,它们可以未被使用,但我们应该将它们与诸如
assert_called_once
或assert_called_once_with
类的模拟函数一起使用,以确保您的补丁按预期工作。 Please see Example B请参见示例 B
==============Example A================== ==============示例A==================
import unittest
def my_basic_function(value, c):
return c(value).words()
class BasicClass:
def __init__(self, val):
self.val = val
def words(self):
return self.val
class TestMyBasicFunction(unittest.TestCase):
def test_my_basic_class(self):
value = my_basic_function("jeremy", BasicClass)
self.assertEqual("jeremy", value)
def test_my_basic_class_wrong(self):
value = my_basic_function("jeremy", BasicClass)
self.assertNotEqual("w33b", value)
============Example B====================== ============示例B======================
import unittest
from unittest.mock import patch
def ensure_str(value):
try:
return str(value)
except Exception:
raise TypeError
def my_basic_function(value, c):
value = ensure_str(value)
return c(value).words()
class BasicClass:
def __init__(self, val):
self.val = val
def words(self):
return self.val
class TestMyBasicFunction(unittest.TestCase):
@patch('script.ensure_str', return_value="jeremy")
def test_return_value(self, ensure_str_mock):
value = my_basic_function("jeremy", BasicClass)
ensure_str_mock.assert_called_once_with("jeremy")
self.assertEqual("jeremy", value)
@patch('script.ensure_str')
def test_no_return_value(self, ensure_str_mock):
value = my_basic_function("jeremy", BasicClass)
self.assertEqual(ensure_str_mock(), value)
@patch('script.ensure_str', side_effect=TypeError)
def test_side_effect(self, ensure_str_mock):
with self.assertRaises(TypeError):
value = my_basic_function({'apple': 'sauce'}, BasicClass)
ensure_str_mock.assert_called_once_with({'apple': 'sauce'})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.