在Django单元测试中取消模拟对象

时间:2012-12-04 01:04:07

标签: django mocking

我的django应用程序中有几个TestCase类。在其中一些中,我模拟了一个函数,它通过使用@ mock.patch修改类来调用外部资源,这非常有用。我的测试套件中的一个TestCase,我们称之为B(),依赖于外部资源,因此我不希望它被模拟,我不添加装饰器。它看起来像这样:

@mock.patch("myapp.external_resource_function", new=mock.MagicMock)
class A(TestCase):
    # tests here

class B(TestBase):
    # tests here which depend on external_resource_function

当我独立测试B时,事情按预期工作。但是,当我同时运行两个测试时,A首先运行,但该功能仍然在B中模拟出来。我怎么能取消该调用?我已经尝试重新加载模块,但它没有帮助。

2 个答案:

答案 0 :(得分:5)

补丁有start and stop methods。根据我从您提供的代码中看到的内容,我将删除装饰器并使用类中链接中的setUp和tearDown方法。

class A(TestCase):
  def setUp(self):
    self.patcher1 = patch('myapp.external_resource_function', new=mock.MagicMock)
    self.MockClass1 = self.patcher1.start()

  def tearDown(self):
    self.patcher1.stop()

  def test_something(self):
    ...

>>> A('test_something').run()

答案 1 :(得分:1)

很棒的答案。关于Ethereal的问题,补丁对象的使用非常灵活。

这是进行需要不同补丁的测试的一种方法。您仍然可以使用setUp和tearDown,但不能使用patch.start / stop位。

你开始()每个测试中的补丁,你使用finally子句来确保它们被停止()。

补丁也支持Context Manager的东西,这是另一个选项,这里没有显示。

class A(TestCase):
    patcher1 = patch('myapp.external_resource_function', new=mock.MagicMock)
    patcher2 = patch('myapp.something_else', new=mock.MagicMock)


    def test_something(self):

        li_patcher = [self.patcher1]
        for patcher in li_patcher:
            patcher.start()


        try:
            pass
        finally:
            for patcher in li_patcher:
                patcher.stop()


    def test_something_else(self):

        li_patcher = [self.patcher1, self.patcher2]
        for patcher in li_patcher:
            patcher.start()

        try:
            pass
        finally:
            for patcher in li_patcher:
                patcher.stop()