Home > Software engineering >  Mocking/patching an object attribute to test a method
Mocking/patching an object attribute to test a method

Time:03-14

I'm testing my code with pytest and am trying to figure out the most direct way to test one of my class' methods.

I have a class like:

class MyClass():
    def __init__(self, stuff):
     ...
    ..
    ..
    def _method_of_interest(self, list1, list2):
        
        ..some logic that depends on list1, list2, and self.relevant_info
  
        return output 

I'd like to test the method _method_of_interest as a function of some list1, list2, and self.relevant_info combinations. I'd prefer to not have to instantiate a real object of MyClass because elsewhere in the logic chain there's some time-consuming computations and I can't easily create objects which have the full range of self.relevant_info values I'd like to test.

What is the cleanest way for me to test the output of this method, with varying list1, list2, and self.relevant_info values?

For concreteness, we can pretend that _method_of_interest is something like:

def _method_of_interest(list1, list2):
    return list1   list2   list(self.relevant_info)

where self.relevant_info is a python set() object.

Any pointers? There's a lot on mocking, patching, etc. online but the examples all look more complicated than my case and the variety of ways one can solve the problem is making me uncertain which way would be the cleanest.

CodePudding user response:

If you want to test a method in complete isolation from the rest of the class, you can always pass a mock self:

# code under test
class MyClass():
    def __init__(self):
        raise NotImplementedError  # don't instantiate me!

    def _method_of_interest(self, list1, list2):
        return list1   list2   list(self.relevant_info)


# test
from unittest.mock import Mock

def test_method_of_interest():
    assert MyClass._method_of_interest(
        Mock(relevant_info=[3]), [1], [2]
    ) == [1, 2, 3]

If you run the test, you'll see that it passes, and that MyClass is never instantiated.

  • Related