Python'call_command'模拟也用于其他测试

时间:2018-10-15 13:20:45

标签: python django unit-testing

使用Django 1.10和python 3.5.1。

我正在尝试模拟'call_command'函数以引发异常。问题在于,它似乎在获得“ side_effect”功能的那一刻-在其他测试中也同样如此。我在做错什么,或者如何从该函数“恢复” 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)

1 个答案:

答案 0 :(得分:0)

您不应修补模块本地名称空间(即Python的“全局”-实际上是“模块”)名称空间中的函数。

在Python中执行

from module.that import this

this成为包含import语句的模块上的变量。对“ 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可以检测到的任何东西的状态。

相关问题