python - 如何正确模拟实例化类变量的函数?
问题描述
我的源文件中有类似的东西
# code.py
def some_func():
# doing some connections and stuff
return {'someKey': 'someVal'}
class ClassToTest:
var = some_func()
我的测试文件看起来像这样......我试图模拟some_func
,因为我想避免创建连接。
# test_code.py
from src.code import ClassToTest
def mock_function():
return {"someOtherKey": "someOtherValue"}
class Test_Code(unittest.TestCase):
@mock.patch('src.code.some_func', new=mock_function)
def test_ClassToTest(self):
self.assertEqual(ClassToTest.var, {"someOtherKey": "someOtherValue"})
但这不起作用。另一方面,如果var
是即时变量模拟工作正常。我猜这是由于类变量在导入期间被初始化。在初始化some_func
之前如何正确模拟?var
解决方案
导入code.py
的时候还没有激活补丁,所以ClassToTest.var
初始化的时候使用的是原来的some_func
. 只有这样补丁src.code.some_func
才能生效,现在显然为时已晚。
解决方案 1
您可以做的是修补some_func
然后重新加载code.py
,以便它重新初始化ClassToTest
包括其属性var
。因此,由于我们在重新加载时已经有一个活动补丁code.py
,因此ClassToTest.var
将使用补丁值进行设置。
- 但是如果类和补丁函数都在同一个文件中,我们就不能这样做,所以为了使它可测试移动
some_func
到另一个文件,然后只导入它。
src/code.py
from src.other import some_func
class ClassToTest:
var = some_func()
源/其他.py
def some_func():
# doing some connections and stuff
return {'realKey': 'realValue'}
测试代码.py
from importlib import reload
import sys
import unittest
from unittest import mock
from src.code import ClassToTest # This will always refer to the unpatched version
def mock_function():
return {"someOtherKey": "someOtherValue"}
class Test_Code(unittest.TestCase):
def test_real_first(self):
self.assertEqual(ClassToTest.var, {"realKey": "realValue"})
@mock.patch('src.other.some_func', new=mock_function)
def test_mock_then_reload(self):
# Option 1:
# import src
# reload(src.code)
# Option 2
reload(sys.modules['src.code'])
from src.code import ClassToTest # This will be the patched version
self.assertEqual(ClassToTest.var, {"someOtherKey": "someOtherValue"})
def test_real_last(self):
self.assertEqual(ClassToTest.var, {"realKey": "realValue"})
输出
$ pytest -q
... [100%]
3 passed in 0.04s
解决方案 2
如果您不希望some_func
在测试期间调用真实数据,那么仅重新加载是不够的。需要做的是永远不要导入包含该文件的文件,ClassToTest
也不要导入任何会间接导入它的文件。仅在已建立活动补丁some_func
后才导入它。
from importlib import reload
import sys
import unittest
from unittest import mock
# from src.code import ClassToTest # Remove this import!!!
def mock_function():
return {"someOtherKey": "someOtherValue"}
class Test_Code(unittest.TestCase):
@mock.patch('src.other.some_func', new=mock_function)
def test_mock_then_reload(self):
from src.code import ClassToTest # Move the import here once the patch has taken effect already
self.assertEqual(ClassToTest.var, {"someOtherKey": "someOtherValue"})
推荐阅读
- tsql - 如何在sql server中的触发器上的同一事务中插入不同的数据库表?
- julia - randsample 函数是否在 Julia 中退出?
- javascript - 重复加载同一页面使 Angular 应用程序变慢
- javascript - 如何在 Vue 中发送 XML 格式的请求?
- dart - getter 中的未来对象
- python-3.x - 如何连接 3 列以在 python 中创建时间序列?
- python - os.getenv 在函数中返回空列表
- php - 在 PHP 中的 URL 跟踪
- python - 具有 Python C 扩展的类(不是方法)的完整和最小示例?
- javascript - 将分号附加到导入语句时,意外的令牌导入