【问题标题】:How to unit test methods inside django's class based views?如何在 django 的基于类的视图中对方法进行单元测试?
【发布时间】:2016-02-12 06:18:06
【问题描述】:

我需要在 django 基于类的视图中测试方法和辅助函数。

考虑这个基于类的视图:

class MyClassBasedView(View):

    def dispatch(self, request, *args, **kwargs):
        ....

    def __get_render_dict():
        d = {}
        ...
        return d

    def my_method(self):
        render_dict =  self.__get_render_dict()
        return render_response(self.request, 'template.html', render_dict)

为了为我的视图编写单元测试,我需要调用里面的方法,直接说__get_render_dict()。我怎样才能做到这一点?。

我试过了

v = MyClassedBasedView() 
v.dispatch(request,args, kwargs)
v.__method_name()

但这会失败,因为 post/get 方法中的参数不匹配,即使我在不​​使用 URL 的情况下直接调用该方法。

【问题讨论】:

  • __get_render_dict 中的方法是什么意思?
  • 咳咳……你为什么要直接实例化 CBV(和调度)? Django 会为您执行此操作,只需将 urls.py 中的视图插入为 url(r'whateverpattern$',MyClassBasedView.as_view(), name='viewname'),
  • 另外,请正确缩进您的代码,以确保我们都理解相同的内容。
  • 我的回答解决了你的问题吗?如果是,请接受,如果不是,请说明您的问题。

标签: python django unit-testing django-class-based-views


【解决方案1】:

要在单元测试中使用基于类的视图,请尝试 setup_view from here

def setup_view(view, request, *args, **kwargs):
    """
    Mimic ``as_view()``, but returns view instance.
    Use this function to get view instances on which you can run unit tests,
    by testing specific methods.
    """

    view.request = request
    view.args = args
    view.kwargs = kwargs
    return view

你仍然需要给它一个请求,你可以使用django.test.RequestFactory

    factory = RequestFactory()
    request = factory.get('/customer/details')

然后您可以对您的方法进行单元测试:

v = setup_view(MyClassedBasedView(), request) 
v.method_name()

【讨论】:

  • 是的,我确实将它用于单元测试。但是,我确实想调用未映射到任何 URL 的特定辅助函数:比如/customer/details 调用 func1,调用者为 helper 1。我如何调用 helper1?
  • setup_view 返回视图对象。然后您可以调用Myview.helper(*args),即使它不是由传递的 url 调用的。 setup_view 不调用 dispatch
  • 感谢更新!我还能打电话给dispatch 吗?因为它添加了一些变量,即self.foo,所有其他方法都将使用这些变量。
  • 如果你想调用不同的方法,你正在编写一个集成测试。如果要对辅助方法进行单元测试,只需自己添加变量即可。:v.foo=5
  • 只需使用v.helper_method() __ 将此方法标记为魔术。说明请参考stackoverflow.com/questions/1301346/…
【解决方案2】:

更新 - 在 Django 3.0 中可用

正如Sebastian's answer 中所述,他从django-downloadview docs 获得了代码sn-p。他们在那里声明:

这是https://code.djangoproject.com/ticket/20456的早期实现

几年后,这个功能现在是 Django 的一部分,你可以read in the docs,所以你只需要这样做:

from django.test import RequestFactory, TestCase
from .views import MyClassBasedView

class MyClassBasedViewTest(TestCase):
  def test_my_method(self):
    request = RequestFactory().get('/')
    view = MyClassBasedView()
    view.setup(request)

    view.my_method()

view.setup() 方法正是接受的答案中建议的方法,但我认为最好使用 Django 中的方法 :)

【讨论】:

  • 如果我尝试 view.get(),这会引发错误 TypeError: get() missing 1 required positional argument: 'request'。大多数(如果不是全部)视图方法不都将请求作为参数吗?
【解决方案3】:

我通过MyClassedBasedView.as_view()(request)解决了这个问题

【讨论】:

  • 这是正确的。唯一需要注意的是,从 URL 模式中提取的任何变量都不会自动完成,因此您需要在调用中手动指定这些参数。因此,如果您的 URL 模式捕获了“”,那么您可以将视图称为:MyClassedBasedView.as_view()(request, slug="some-slug")
猜你喜欢
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-29
  • 2016-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多