Search code examples
pythondjangopython-3.xdjango-class-based-viewsdjango-unittest

How to mock a specific method of a class based View without overriding `self`?


I am trying to patch a function of a view within a TestCase in django. I have a class:

class BaseView(View):

    def _get_data(self):
        self.attribute = self.fancy_stuff()
        self.thing = self.do_other_stuff()

I need to mock out self.attribute to an empty list like:

_get_data_fake_function():
    self.attribute = []
    self.thing = True

An issue is that I'm within a test case like:

class MyTests(TestCase):

    def setUp(self):
        self.view = BaseView
        self.view_instance = self.view()

        def test_stuff(self):
            with patch(self.view) as mock_view:
                ?

I fear the self is going to refer to the TestCase instance, and I'm confused on how to patch in the with patch(thing) as name part. I could patch the view's or the view instance's method, but either way I don't know how the fake function will correctly set the view's attribute and thing, not the test cases.


Solution

  • Patch the _get_data method on BaseView to have a side_effect that sets the appropriate instance variables on the view.

    class MyTests(TestCase):
    
        def setUp(self):
            self.view = BaseView
            with patch.object(self.view, '_get_data', side_effect=view_data_mock):
                self.view_instance = self.view()
    
        def test_stuff(self):
            self.assertEqual([], self.view_instance.attribute)
            self.assertTrue(self.view_instance.thing)
    
    def view_data_mock(view):
        view.attribute = []
        view.thing = True