我的 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 中运行的代码的设置?
感谢您的宝贵时间。
正如您在上面所写的,
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)