pythonpython-unittestpython-unittest.mock

Mocking Enum using unittest.mock does not work as expected


I'm trying to Mock an enum in Python so that I can assert whether a method of the class tested calls a method on the enum.

This does not work as expected. The method in question is never called because an identity comparison of the mock with the actual enum always fails.

class ProcessorTest(unittest.TestCase):
    def test_do_something(self):
        # Mock library does not work with enums..
        self.mock_camera = mock.create_autospec(Camera.exit)

        self.processor.process(self.mock_camera)

        # => always leads to "failed"
        self.assertTrue(self.mock_camera.do_something.called,
                        "Failed")

class Camera(Enum):
    entrance = 1
    exit = 2

    def do_something(self):
        return True

class Processor:
    def process(self, camera):
        # this comparison always resolves to false
        if camera is Camera.exit:
            # never reached
            camera.do_something()

Solution

  • Rather than trying to create a mock member of an enumeration, just patch that method:

    from enum import Enum
    import unittest
    
    
    class Camera(Enum):
        entrance = 1
        exit = 2
    
        def do_something(self):
            return True
    
    
    class Processor:
    
        def process(self, camera):
            if camera is Camera.exit:
                camera.do_something()
    
    
    class TestProcessor(unittest.TestCase):
    
        def test_processor_process(self):
            with unittest.mock.patch.object(Camera, 'do_something') as mock_method:
                Processor().process(Camera.exit)
                mock_method.assert_called_once_with()
    
    
    if __name__ == '__main__':
        unittest.main()
    

    Now you can pass a real member, but intercept calls to do_something. This gets around the fact that there's no way to mock identity.