【问题标题】:Django UrlResolver, adding urls at runtime for testingDjango UrlResolver,在运行时添加 url 进行测试
【发布时间】:2011-06-21 00:04:39
【问题描述】:

我正在做一些测试,我对URLResolver 还不是很熟悉,但我想快速解决这个问题。

TestCase 中,我想向解析器添加一个URL,这样我就可以使用Client.get('/url/') 并将其与urls.py 分开。

【问题讨论】:

    标签: django unit-testing url testcase


    【解决方案1】:

    https://docs.djangoproject.com/en/2.1/topics/testing/tools/#urlconf-configuration

    在你的测试中:

    class TestMyViews(TestCase):
         urls = 'myapp.test_urls'
    

    这将使用myapp/test_urls.py 作为ROOT_URLCONF

    【讨论】:

    • 对于未来的访问者,请注意@renskiy 添加的更合适的(对于现代 Django 版本)答案。
    【解决方案2】:

    我知道这是不久前提出的问题,但我想我会再次回答它以提供更完整和最新的内容。

    您有两种选择来解决这个问题,一种是提供您自己的 urls 文件,正如 SystemParadox 的回答所建议的那样:

    class MyTestCase(TestCase):
        urls = 'my_app.test_urls'
    

    另一个是修改你的网址。这不是处理覆盖 url 的推荐方法,但您可能会遇到仍然需要它的情况。要在不影响其余测试用例的情况下执行此操作,您应该在 setUp() 方法中执行此操作,然后在您的 tearDown() 方法中进行清理。

    import my_app.urls
    from django.conf.urls import patterns
    
    class MyTestCase(TestCase):
        urls = 'my_app.urls'
    
        def setUp(self):
            super(MyTestCase, self).setUp()
            self.original_urls = my_app.urls.urlpatterns
            my_app.urls.urlpatterns += patterns(
                '',
                (r'^my/test/url/pattern$', my_view),
            )
    
        def tearDown(self):
            super(MyTestCase, self).tearDown()
            my_app.urls.urlpatterns = self.original_urls
    

    请注意,如果您省略 urls 类属性,这将不起作用。这是因为 URL 将被缓存,如果您将测试与其他测试用例一起运行,您的猴子补丁将不会生效。

    【讨论】:

    • 但是你为什么要这样做,当你不能正确声明某些东西时,使用猴子路径作为最后的手段。在这里,您明确设置了“my_app.urls”,只是在几行之后更改它!
    • 这当然不是一般覆盖测试 url 的推荐方法 - my_app.urls 在这种情况下是默认的应用程序 urls 模块,而不是特定于测试的模块,它是强制重新加载 url 的一种 hacky 方式。我刚刚添加它是因为我遇到了一个案例,猴子修补实际上需要比重新创建整个 urls 模块更费力的代码。
    【解决方案3】:

    自 Django 1.8 using of django.test.TestCase.urls is deprecated.您可以改用django.test.utils.override_settings

    from django.test import TestCase
    from django.test.utils import override_settings
    
    urlpatterns = [
        # custom urlconf
    ]
    
    @override_settings(ROOT_URLCONF=__name__)
    class MyTestCase(TestCase):
        pass
    

    override_settings 可以应用于整个类或特定方法。

    【讨论】:

    • 这完全覆盖了 urlpatterns。如果我想添加它们怎么办?
    • @Joost 你可以做类似from myapp.urls import urlpatterns as base_patterns 然后urlpatterns = base_patterns + [<your custom patterns here>]
    • 我必须在我的测试中添加 self.reload_urlconf() 以强制重新加载,以及使用 @override_settings(ROOT_URLCONF=__name__)
    • from myapp.urls import urlpatterns as base_patterns 对我不起作用,因为我对所有其他 URL 的测试都依赖于完整路径。我不得不做my_project.urls import urlpatterns as base_patterns。另外,因为它是my_project.urls,所以我必须在测试中编写完整路径(例如/myapp/path/to/my/view 而不是/path/to/my/view)。
    【解决方案4】:

    无法使用上述答案运行它。甚至没有override_settings。 找到了一个适合我的解决方案。我的用例是编写一些集成测试,我想在我需要应用程序的 url 的地方测试 put/post 方法。

    这里的主要线索是使用django.urlsset_urlconf函数,而不是在类中覆盖它或使用override_settings

    from django.test import TestCase
    from django.urls import reverse, set_urlconf
    
    class MyTests(TestCase):
        @classmethod
        def setUpClass(cls):
            super().setUpClass()
            set_urlconf('yourapp.urls')  # yourapp is the folder where you define your root urlconf.
    
        def test_url_resolving_with_app_urlconf(self):
            response = self.client.put(
                path=reverse('namespace:to:your:view-name'), data=test_data
            )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-29
      • 1970-01-01
      相关资源
      最近更新 更多