在测试过程中,如何在Django的模型中修改装饰器? [英] How can I monkey-patch a decorator in Django's models while testing?
问题描述
@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屋!