在类方法中模拟一个函数

时间:2015-04-05 14:28:32

标签: python django unit-testing mocking

我想模拟一个在类方法中调用的函数,同时在Django项目中测试类方法。考虑以下结构:

应用程序/ utils.py

def func():
    ...
    return resp  # outcome is a HTTPResponse object

应用程序/ models.py

from app.utils import func

class MyModel(models.Model):

    # fields

    def call_func(self):
        ...
        func()
        ...

应用程序/测试/ test_my_model.py

from django.test import TestCase
import mock    

from app.models import MyModel

class MyModelTestCase(TestCase):

    fixtures = ['my_model_fixtures.json']

    def setUp(self):
        my_model = MyModel.objects.get(id=1)

    @mock.patch('app.utils.func')
    def fake_mock(self):
        return mock.MagicMock(headers={'content-type': 'text/html'},
                              status_code=2000, 
                              content="Fake 200 Response"))

    def test_my_model(self):
        my_model.call_func()
        ...  # and asserting the parameters returned by func

当我运行测试时,避免使用模拟函数fake_func,而是调用真实的func。我想mock.patch装饰器中的范围可能是错误的,但我找不到使其工作的方法。我该怎么办?

2 个答案:

答案 0 :(得分:4)

您的代码有三个问题:

1)正如Daniel Roseman所提到的,你需要修改调用函数的模块,不是它定义的位置

2)此外,您需要修饰实际执行调用模拟函数的代码的测试方法。

3)最后,您还需要将模拟版本作为参数传递给您的测试方法,可能是这样的:

fake_response = mock.MagicMock(headers={'content-type': 'text/html'},
                          status_code=2000, 
                          content="Fake 200 Response"))


class MyModelTestCase(TestCase):

    fixtures = ['my_model_fixtures.json']

    def setUp(self):
        my_model = MyModel.objects.get(id=1)

    @mock.patch('app.models.func', return_value=fake_response)
    def test_my_model(self, fake_response):  # the mock goes in as a param or else you get number of arguments error!
        my_model.call_func()
        self.assertTrue(fake_response.called)

答案 1 :(得分:1)

正如docs解释的那样,你需要在它被调用的地方模拟func,而不是在它被定义的地方。所以:

@mock.patch('app.models.func')