totoro
totoro

Reputation: 3407

How to unit test methods inside django's class based views?

I need to test the methods and helper function inside a django Class Based View.

Consider this Class Based View:

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)

In order to write unit tests for my view, I need to call the methods inside, say __get_render_dict() directly. How can I achieve this?.

I've tried

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

but this fails with not matching parameters in post/get method, even though I was calling the method direclty without using URL.

Upvotes: 19

Views: 17132

Answers (3)

NBajanca
NBajanca

Reputation: 3720

Update - available in Django 3.0

As stated in Sebastian's answer he got the code snippet from django-downloadview docs. In there they state:

This is an early implementation of https://code.djangoproject.com/ticket/20456

A few years later, this feature is now part of Django, as you can read in the docs, so you would just need to do:

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

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

    view.my_method()

The view.setup() method is precisely what was suggested in the accepted answer, but I think it is better to use the one from Django :)

Upvotes: 18

Sebastian Wozny
Sebastian Wozny

Reputation: 17506

To use class based views in your unittests try 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

You still need to feed it a request, you can do this with django.test.RequestFactory:

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

You can then unittest your methods:

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

Upvotes: 27

Thom
Thom

Reputation: 1623

I solved this issue by doing MyClassedBasedView.as_view()(request)

Upvotes: 9

Related Questions