python 模拟补丁装饰器对 class 方法和单个函数的行为不同
python mock patch decorator behaves different for class methods and individual functions
好几次我 运行 遇到 unittest.mock.patch
装饰器的问题。当我尝试从包含的模块模拟单个函数时,patch
不起作用。但是,如果包含模块中的函数被收集为 class 方法,则 patch
可以完美运行。
这个 question 部分与我的相交。但是这个问题也没有很好的答案。
这是我要描述的示例:
|-- __init__.py
|-- helpers.py
|-- main_module.py
|-- tests.py
我在 helpers.py
中写了一个函数作为 class 方法,另一个函数作为单独的函数:
# helpers.py
class HelperClass():
def method_a(self):
return "a"
def function_a():
return "a"
我已将它们都包含在主模块中:
# main_module.py
from helpers import HelperClass, function_a
def function_which_uses_helper_function():
a_val = function_a()
return a_val
def function_which_uses_helper_class_method():
a_val = HelperClass().method_a()
return a_val
最后测试:
# tests.py
from unittest import TestCase
from unittest.mock import patch
from main_module import function_which_uses_helper_function, function_which_uses_helper_class_method
class TestClass(TestCase):
@patch('helpers.function_a')
def test_function_which_uses_helper_function(self, mock_function_a):
mock_function_a.return_value = "c"
self.assertEqual(function_which_uses_helper_function(), "c")
@patch('helpers.HelperClass.method_a')
def test_function_which_uses_helper_class_method(self, mock_method_a):
mock_method_a.return_value = "c"
self.assertEqual(function_which_uses_helper_class_method(), "c")
这给了我这些结果:
$ py.test tests.py
<...>
tests.py .F
<...>
tests.py:11: in test_function_which_uses_helper_function
self.assertEqual(function_which_uses_helper_function(), "c")
E AssertionError: 'a' != 'c'
E - a
E + c
============ 1 failed, 1 passed in 0.14 seconds ============
如有任何帮助,我将不胜感激。希望这也对某人有所帮助:)
过了一会儿我终于明白为什么我的函数示例不起作用了。解释是 here. And this article 也非常有用。考虑到所有这些解决方案将是:
# main_module.py
import helpers # <- I had to change my import statement
def function_which_uses_helper_function():
a_val = helpers.function_a()
return a_val
def function_which_uses_helper_class_method():
a_val = helpers.HelperClass().method_a()
return a_val
另一个解决方案是改变我模拟 function_a 的方式,即:
from unittest import TestCase
from unittest.mock import patch
from main_module import function_which_uses_helper_function, function_which_uses_helper_class
class TestClass(TestCase):
@patch('main_module.function_a') # <-- !!! I need to mock function in the`main_module`, not in `helpers` !!!
def test_function_which_uses_helper_function(self, mock_function_a):
mock_function_a.return_value = "c"
self.assertEqual(function_which_uses_helper_function(), "c")
@patch('helpers.HelperClass.function_a')
def test_function_which_uses_helper_class(self, mock_function_a):
mock_function_a.return_value = "c"
self.assertEqual(function_which_uses_helper_class(), "c")
很遗憾我最近才意识到这一切。希望这对某人有所帮助:)
好几次我 运行 遇到 unittest.mock.patch
装饰器的问题。当我尝试从包含的模块模拟单个函数时,patch
不起作用。但是,如果包含模块中的函数被收集为 class 方法,则 patch
可以完美运行。
这个 question 部分与我的相交。但是这个问题也没有很好的答案。
这是我要描述的示例:
|-- __init__.py
|-- helpers.py
|-- main_module.py
|-- tests.py
我在 helpers.py
中写了一个函数作为 class 方法,另一个函数作为单独的函数:
# helpers.py
class HelperClass():
def method_a(self):
return "a"
def function_a():
return "a"
我已将它们都包含在主模块中:
# main_module.py
from helpers import HelperClass, function_a
def function_which_uses_helper_function():
a_val = function_a()
return a_val
def function_which_uses_helper_class_method():
a_val = HelperClass().method_a()
return a_val
最后测试:
# tests.py
from unittest import TestCase
from unittest.mock import patch
from main_module import function_which_uses_helper_function, function_which_uses_helper_class_method
class TestClass(TestCase):
@patch('helpers.function_a')
def test_function_which_uses_helper_function(self, mock_function_a):
mock_function_a.return_value = "c"
self.assertEqual(function_which_uses_helper_function(), "c")
@patch('helpers.HelperClass.method_a')
def test_function_which_uses_helper_class_method(self, mock_method_a):
mock_method_a.return_value = "c"
self.assertEqual(function_which_uses_helper_class_method(), "c")
这给了我这些结果:
$ py.test tests.py
<...>
tests.py .F
<...>
tests.py:11: in test_function_which_uses_helper_function
self.assertEqual(function_which_uses_helper_function(), "c")
E AssertionError: 'a' != 'c'
E - a
E + c
============ 1 failed, 1 passed in 0.14 seconds ============
如有任何帮助,我将不胜感激。希望这也对某人有所帮助:)
过了一会儿我终于明白为什么我的函数示例不起作用了。解释是 here. And this article 也非常有用。考虑到所有这些解决方案将是:
# main_module.py
import helpers # <- I had to change my import statement
def function_which_uses_helper_function():
a_val = helpers.function_a()
return a_val
def function_which_uses_helper_class_method():
a_val = helpers.HelperClass().method_a()
return a_val
另一个解决方案是改变我模拟 function_a 的方式,即:
from unittest import TestCase
from unittest.mock import patch
from main_module import function_which_uses_helper_function, function_which_uses_helper_class
class TestClass(TestCase):
@patch('main_module.function_a') # <-- !!! I need to mock function in the`main_module`, not in `helpers` !!!
def test_function_which_uses_helper_function(self, mock_function_a):
mock_function_a.return_value = "c"
self.assertEqual(function_which_uses_helper_function(), "c")
@patch('helpers.HelperClass.function_a')
def test_function_which_uses_helper_class(self, mock_function_a):
mock_function_a.return_value = "c"
self.assertEqual(function_which_uses_helper_class(), "c")
很遗憾我最近才意识到这一切。希望这对某人有所帮助:)