如何在测试时对Django模型中的装饰器进行猴子修补?

时间:2012-12-24 16:40:40

标签: python django testing monkeypatching

我的模型中有一个@memoize装饰器,它会缓存模型本身的一些细节,以避免在多次调用时多次调用数据库(特别是在模板中)。但是,由于我存储了对象并在测试中引用它们,这会破坏事情。

例如,如果我执行mygroup.subscribers,添加订阅者并再次尝试,则会返回不正确数量的订阅者,因为它已被记忆化。

我如何通过我的tests.py来修补那个装饰器什么都不做?我没有找到干净利落的方法,因为模型首先被加载。

2 个答案:

答案 0 :(得分:0)

memoize实施开始时,根据answer检查它是否处于测试模式:

from django.core import mail

# at the beginning of your memoize
if hasattr(mail, 'outbox'):
    # return without memorizing

答案 1 :(得分:0)

您可以在test runner中禁用装饰器,在加载模型之前将设置测试环境。

例如:

from django.test.simple import DjangoTestSuiteRunner
from utils import decorators

class PatchTestSuiteRunner(DjangoTestSuiteRunner):
    def setup_test_environment(self, **kwargs):
        super(PatchTestSuiteRunner, self).setup_test_environment(**kwargs)
        self.__orig_memoize = decorators.memoize
        decorators.memoize = lambda x: x

    def teardown_test_environment(self, **kwargs):
        decorators.memoize = self.__orig_memoize
        super(PatchTestSuiteRunner, self).teardown_test_environment(**kwargs)

然后输入您的settings.py

TEST_RUNNER = 'test.PatchTestSuiteRunner'

测试可以在没有记忆的情况下运行:

# myapp/models.py
class TestObject(object):
    def __init__(self, value):
        self.value = value

    @memoize
    def get_value(self):
        return self.value

# myapp/test.py
from django.test import TestCase
from .models import TestObject

class NoMemoizeTestCase(TestCase):
    def test_memoize(self):
        t = TestObject(0)
        self.assertEqual(t.get_value(), 0)
        t.value = 1
        self.assertEqual(t.get_value(), 1)

请注意,虽然我们要在测试运行器的teardown_test_environment中恢复原始装饰器,但在已装饰的功能上不会恢复通知。如果我们使用更复杂的测试装饰器,可以恢复记忆,但在标准用例中可能不需要这样做。