Emil Terman
Emil Terman

Reputation: 526

Dependency injection in django Views

I want to use dependency injection for my django project. For that I'm trying pinject package. Like in ASP.NET, all the dependencies are given in the constructor, and that's very nice because it's easy to test. I would also like to archive something similar in my django project.

I have a simple View:

class MySimpleView(View):
    def __init__(self, dependency1, dependency2, **kwargs):
        super().__init__(**kwargs)
        ...

A place where I define the bindings

# di.py
class AppBindingSpec(pinject.BindingSpec):
    def configure(self, bind):
        # do the bindings here


obj_graph = pinject.new_object_graph(binding_specs=[AppBindingSpec()])

And I expected to use it like this.

# urls.py
urlpatterns = [
    path('path/to/my/view', obj_graph.provide(MySimpleView).as_view()),
]

But unfortunately, django does not allow the .as_view() to be called from an instance.

Is there any simple way to inject the dependencies into my view so I can easily mock and test?

Upvotes: 2

Views: 2498

Answers (1)

andreashhp
andreashhp

Reputation: 485

If your goal is to provide yourself with an easy and safe way to 'mock and test', then you are probably better of using the mock library provided by unittest (which by the way is also a lot like mocking in .NET). With this, you can do something like this:

from unittest.mock import Mock, patch
from django.tests import TestCase

class MySimpleViewTestCase(TestCase):
    @patch('module_name.dependency2')
    @patch('module_name.dependency1.specific_method_or_attribute')
    def test_something_about_mysimpleview(self, mock_dependency1, mock_dependency2):
        mock_dependency1.return_value = Mock(some_attribute="foo", some_method.return_value="bar")
        mock_dependency2.return_value = 42

        # do your testing of MySimpleView

Now, when the test runs, mock will replace whatever module_name.dependency1.specific_method_or_attribute and module_name.dependency2 was with mock objects. So, when module_name.dependency2() is run, it will return 42, while specific_method() will return a Mockobject with an attribute with the value "foo" and a method some_method() that returns "bar".

You can use this to mock functions, classes or even modules.

Upvotes: 2

Related Questions