在单元测试 django 时如何覆盖 urls.py 中运行的代码的设置

问题描述 投票:0回答:1

我的 django 应用程序有一个环境变量

DEMO
,除其他外,它规定了我的
urls.py
文件中声明的端点。

我想对这些端点进行单元测试,我已经尝试过

django.test.override_settings
但我发现
urls.py
仅运行一次,而不是每个单元测试运行一次。

我的代码如下所示:

# settings.py 

DEMO = os.environ.get("DEMO", "false") == "true"

# urls.py

print(f"urls.py: DEMO = {settings.DEMO}")
if settings.DEMO:
    urlpatterns += [
        path('my_demo_endpoint/',MyDemoAPIView.as_view(),name="my-demo-view")
    ]
# test.test_my_demo_endpoint.py

class MyDemoEndpointTestCase(TestCase):
    @override_settings(DEMO=True)
    def test_endpoint_is_reachable_with_demo_equals_true(self):
        print(f"test_endpoint_is_reachable_with_demo_equals_true: DEMO = {settings.DEMO}")
        response = self.client.get("/my_demo_endpoint/")
        # this fails with 404
        self.assertEqual(response.status_code, 200)

    @override_settings(DEMO=False)
    def test_endpoint_is_not_reachable_with_demo_equals_false(self):
        print(f"test_endpoint_is_not_reachable_with_demo_equals_false: DEMO = {settings.DEMO}")
        response = self.client.get("/my_demo_endpoint/")
        self.assertEqual(response.status_code, 404)

运行此程序时我得到:

urls.py: DEMO = False
test_endpoint_is_reachable_with_demo_equals_true: DEMO = True
<test fails with 404>
test_endpoint_is_not_reachable_with_demo_equals_false: DEMO = False
<test succeed>

urls.py 在每次测试之前仅运行一次,但是我想根据设置测试 urls.py 的不同行为

使用不同的设置文件进行测试并不是解决方案,因为不同的测试需要不同的设置。在单元测试中直接调用我的视图意味着 urls.py 代码保持未覆盖且其行为未经测试,因此这也不是我想要的。

如何覆盖 urls.py 中运行的代码的设置?

感谢您的宝贵时间。

python django testing
1个回答
0
投票

正如您在上面所写的,

urls.py
在应用程序启动期间加载一次,并且不会在测试之间重新加载,除非您明确重新加载它。要根据设置测试不同的
urls.py
行为,您可以在每个测试中动态导入并重新加载
urls.py
模块。

更改设置后,使用Python的

importlib.reload
重新导入并评估
urls.py

import importlib
from django.conf import settings
from django.test import override_settings, TestCase
from django.urls import resolve, reverse

class MyDemoEndpointTestCase(TestCase):
    def reload_urls(self):
        import myproject.urls  # Adjust to your `urls.py` location
        importlib.reload(myproject.urls)
    
    @override_settings(DEMO=True)
    def test_endpoint_is_reachable_with_demo_equals_true(self):
        self.reload_urls()
        self.assertTrue(settings.DEMO)  # Verify setting was applied
        response = self.client.get("/my_demo_endpoint/")
        self.assertEqual(response.status_code, 200)
    
    @override_settings(DEMO=False)
    def test_endpoint_is_not_reachable_with_demo_equals_false(self):
        self.reload_urls()
        self.assertFalse(settings.DEMO)  # Verify setting was applied
        response = self.client.get("/my_demo_endpoint/")
        self.assertEqual(response.status_code, 404)
© www.soinside.com 2019 - 2024. All rights reserved.