在测试期间,如何覆盖 urlconf 中使用的 Django 设置?

During tests, how to override a Django setting used in the urlconf?

在我的 Django 项目的 urlconf 中,我有这样的东西:

from django.conf import settings
from django.conf.urls import include, url

urlpatterns = [
    url(r'^{}/blog'.format(settings.MY_ROOT_DIR),
        include('weblogs.urls')),
    # ...
]

在我的 settings.py 中,我会有这样的东西:

MY_ROOT_DIR = 'phil'

这样我就可以在一个地方(设置)设置多个地方使用的根目录。

当我来测试 URL 时,我使用 @override_settings decorator:

from django.test import TestCase, override_settings
from django.urls import reverse

@override_settings(MY_ROOT_DIR='terry')
class WeblogUrlsTestCase(TestCase):

        def test_post_detail_url(self):
            self.assertEqual(
                reverse('post_detail', kwargs={'slug': 'my-post'}),
                '/terry/blog/my-post/'
            )

然而,@override_settings 似乎没有做任何事情 - urls.py 中使用的 MY_ROOT_DIR 值始终是 "phil",从来没有覆盖 [=19] 的设置=].我也试过 @modify_settings,并在测试方法上使用它,而不是 class。

我猜 urlconf 是在 @override_settings 生效之前由 Django 加载的?有没有解决的办法?或者更好的解决方案?

如您所料,您在将设置导入 url 后覆盖了这些设置。如果您在某些方法中使用了 settings 变量,而不是在 urls.py.

的全局范围内,这将有效

虽然在 运行 时间覆盖设置配置似乎很方便,但在我看来,您应该创建一个单独的文件进行测试。这节省了大量测试配置,这将确保您永远不会做一些不可逆转的事情(比如清理暂存数据库)。

# test_settings.py

MY_ROOT_DIR = 'terry'

假设您的测试文件存在于'my_project/test_settings.py',添加

settings = 'my_project.test_settings' if 'test' in sys.argv else 'my_project.settings'

在你的 manage.py 中。这将确保当你 运行 python manage.py test 时你只使用 test_settings。如果您正在使用其他一些测试客户端,如 pytest,您可以轻松地将其添加到 pytest.ini