在测试过程中,如何在Django的模型中修改装饰器? [英] How can I monkey-patch a decorator in Django's models while testing?

查看:122
本文介绍了在测试过程中,如何在Django的模型中修改装饰器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



例如,如果我执行 mygroup.subscribers ,添加一个订阅者再次尝试一次,它将返回不正确的订阅者数量,因为它被记住了。



decorator从我的tests.py中做什么?我没有找到干净的方法,因为模型首先被加载。

解决方案

你可以禁用你的装饰器测试环境测试运行器将在模型加载之前设置。



例如:

 从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 中的装饰器,在已装饰的f上将不会恢复备忘录unctions。如果我们使用更复杂的测试装饰器,则可以恢复备份,但这在标准用例中可能不是必需的。


I have a @memoize decorator in my models, which caches some details on the model itself, to avoid multiple database calls when called many times (especially in templates). However, since I store the objects and refer to them in tests, this breaks things.

For example, if I do mygroup.subscribers, add a subscriber and try it again, it will return an incorrect number of subscribers, since it's been memoized.

How can I monkey-patch that decorator to do nothing from my tests.py? I haven't found a way to do it cleanly, since models get loaded first.

解决方案

You can disable your decorator in your test runner, the test environment will be set up before models are loaded.

For example:

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)

Then put in your settings.py:

TEST_RUNNER = 'test.PatchTestSuiteRunner'

And the tests can be run without memoization:

# 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)

Note that although we're restoring the original decorator in the test runner's teardown_test_environment, memoization will not be restored on already decorated functions. Memoization could be restored if we use a more complex testing decorator, but this is probably not required in standard use cases.

这篇关于在测试过程中,如何在Django的模型中修改装饰器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆