python - Python 'call_command' mock 也用于其他测试
问题描述
使用 Django 1.10 和 python 3.5.1。
我正在尝试模拟“call_command”函数来引发异常。问题在于,它似乎在获得“side_effect”功能的那一刻 - 它也保留用于其他测试。我在做什么错或如何从该功能“恢复”副作用?
在此示例中,在运行其中一个测试之后,之后运行的所有其他测试将抛出相同的异常,即使它不应该在该测试中抛出异常。
def test_run_migrations_raise_exception(self):
with mock.patch('django.core.management.call_command', return_value=None, side_effect=Exception('e message')):
self.check_migrations_called(MigrationTracker.objects.all(), data_migrations_settings_in_db)
call_command('run_data_migrations')
self.check_migrations_called(MigrationTracker.objects.all(), data_migrations_settings_in_db)
def test_run_migrations_raise_flow_exception(self):
with mock.patch('django.core.management.call_command', return_value=None, side_effect=FlowException(500, 'fe message', {'a': 1})):
self.check_migrations_called(MigrationTracker.objects.all(), data_migrations_settings_in_db)
call_command('run_data_migrations')
self.check_migrations_called(MigrationTracker.objects.all(), data_migrations_settings_in_db)
解决方案
您不应该修补位于模块本地(即 Python 的“全局”-实际上是“模块”)命名空间中的函数。
当你在 Python 中时
from module.that import this
this
成为包含导入语句的模块上的变量。对“module.that.this”的任何更改都会影响到另一个模块中指向的对象,但仅使用this
仍会冷却到原始对象。
也许您的代码与您向我们展示的不完全一样,或者“mock.pacth”可能会在制作补丁时发现模块本地call_command
指向django.core.management.call_command
另一个模块 - 但在反转补丁时不会。事实是您的模块本地名称call_command
正在更改。
您可以通过简单地更改代码以不将模块变量直接绑定到要更改的函数来解决此问题:
从 django.core 导入管理 def test_run_migrations_raise_exception(self):
with mock.patch('django.core.management.call_command', return_value=None, side_effect=Exception('e message')):
self.check_migrations_called(MigrationTracker.objects.all(), data_migrations_settings_in_db)
management.call_command('run_data_migrations')
self.check_migrations_called(MigrationTracker.objects.all(), data_migrations_settings_in_db)
我希望你能理解并解决这个问题。现在,也就是说,这种使用mock
完全没有意义:使用模拟的想法是,您在应用补丁的代码块中调用的代码间接使用的一些可调用对象没有原始效果 - 所以中间代码可以运行并进行测试。您正在直接调用模拟对象 - 所以它不会有任何原始代码 - 调用call_command('run_data_migrations')
根本不会在您的代码库上运行任何代码,因此没有什么可以测试的。它只是调用模拟实例,它不会改变任何可以用check_migrations_called
.
推荐阅读
- java - InvalidPluginException: UnsupportedClassVersionError: JVMCFRE003 bad major version;class=ml/commandermc/rtp/Main, offset=6 Minecraft 插件
- swift - 如何与 siwft 4 共享生成的 UIImage
- c++ - 注入一个 QTimer 的模拟
- php - 我们可以使用 mysqli_real_escape_string 来防止搜索表单中的 SQLinjection 吗?
- python - 计算不平衡的 4D numpy 数组中的元素数
- java - Java Spring SOAP Webservice 中的 JBoss (Wildfly) max-post-size 句柄响应
- reactjs - Reducer 正在接收参数但什么也没做 ReactJS
- reactjs - PropTypes:PropTypes.array VS PropTypes.arrayOf(PropTypes.any)
- c++ - 使用 gnuPlot 在 C++ 中进行实时绘图
- python - 如何以迭代的方式用熊猫平均单个列中的两个值?