3

I cannot instantiate an object because it is an abstract class, so I have to use mocking in order to test my code.

I have been told this is best done by creating a new mock class.

class MockMyClass(MyClass):
    def my_first_function(...):

The idea is that I then instantiate a MockMyClass object, where I can test private function in that.


I have read the python guide and researched other stack questions. Here, the theory behind mock has been well explained. Unfortunately, I am still lost with how mocking can be used in a large unittest for multiple functions. For instance:

If I have a class, from which other classes in the main code inherit functions from. This can take the form:

class SharedFunctions(AnotherClass):
    first_function():
        #do some important calculations to generate stuff.#
        self.stuff = first_function_attribute_stuff

        return returned_first_stuff

    second_functions(returned_stuff)
        returned_second_stuff = self.stuff + returned_first_stuff
        
        return returned_second_stuff

and where the class SharedFunctions also inherits from another class (noting the abstract method) of the form:

class AnotherClass():
    @abc.abstractmethod
    def one_important_universal_function(...):
        pass

I have tried to construct a unittest for the SharedFunctions piece of code.


This is what I have tried so far:

class MockSharedFunctions(SharedFunctions):
    def first_function(...):
        self.stuff = some value
        returned_first_stuff = given some other value

        return returned_first_stuff

    def second_function
        returned_second_stuff = another value.

        return returned_second_stuff

class TestSharedFunctions(unittest.TestCase):
    def test_first_function(self):
        # insert code #

        self.assertTrue(True)

    def test_second_function(self):
        # insert code #

        self.assetEqual(output, expected)
        self.assertTrue(True)

if __name__ == "__main__":
    unittest.main()

Where insert code has been a number of various attempts to use mocking. However, I have not come across a clear example of how mock functions can be used to replace other functions, or a confirmation that this will work.

Thank you for any help.

Wychh
  • 469
  • 3
  • 11
  • 2
    Did you have a look at `mock.patch`? Basically, you have to replace all objects you don't want to call in the test with mock objects (using `patch`), and configure these if needed. Your example code is very abstract, so it is not clear what you actually want to test - it would help to put a more concrete example here (instead of just `assert True`) to understand what are you going to test. – MrBean Bremen Aug 10 '20 at 16:23
  • Thank you @MrBeanBremen. I had looked at the youtube video https://www.youtube.com/watch?v=GYkGguhdqw0 which showed the usage of patches. However, I couldnt see how this would apply to my case. Also, thank you pointing out that my question is a bit too generic. I was hoping this would help for other users, I will try and make it more specific when I get a spare moment. – Wychh Aug 10 '20 at 17:32

1 Answers1

2

A common issue is too over complicate the use of mocking functions. You can almost treat them like another class method. In your case, the abstractmethod decorator is probably generating the confusion.

This is something close to what you might need.

class MockSharedFunctions(SharedFunctions):
    def one_important_universal_function(**args):
        return 0

class TestSharedFunctions(unittest.TestCase):
    def test_first_function(self):
        mock = MockSharedFunctions()
        mock_output = firstfunction(**args)
        mock_stuff = mock.stuff

        self.assertTrue(True)
        self.assetEqual(mock_output, expected)
        self.assetEqual(mock_stuff, expected)

    def test_second_function(self):
        mock = MockSharedFunctions()
        mock.stuff = some_value
        mock_output = second_function(**args)

        self.assetEqual(mock_output, expected)
        self.assertTrue(True)

if __name__ == "__main__":
    unittest.main()

Here, in the MockSharedFunctions you are already inheriting SharedFunctions. As one_important_universal_function is an abstract method, it needs to be defined.