2

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()
edwardmp
  • 6,339
  • 5
  • 50
  • 77
  • Have you tried patching that method, rather than replacing the whole enumerator member? There's no way to mock identity. – jonrsharpe Oct 30 '16 at 21:36
  • @jonrsharpe thanks, that worked. Kind of new with testing in Python but indeed you can't mock identity. This worked: `Camera.exit.do_something = mock.MagicMock()` and `self.assertTrue(Camera.exit.do_something.called, "failed")` – edwardmp Oct 30 '16 at 21:47

1 Answers1

1

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.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • Just solved it on my own based on your comment but I'll gladly accept your answer – edwardmp Oct 30 '16 at 21:48
  • @edwardmp you're welcome to post your own answer if you did it differently. Note that it's better to correspond with your own example - what is `open_barrier`? – jonrsharpe Oct 30 '16 at 21:49