[Python] How to test the concrete method of an abstract class without manual subclassing?

Discussão em 'Python' iniciado por Stack, Agosto 13, 2025.

  1. Stack

    Stack Membro Participativo

    I have an abstract Python class with a concrete method:

    class AbstractFoo(abc.ABC):
    def append_something(self, text: str) -> str:
    return text + self.create_something(len(text))

    @abc.abstractmethod
    def create_something(self, number: int) -> str:
    raise NotImplementedError()

    # IMPORTANT: many other abstract methods irrelevant for the test omitted here


    Given that there are many abstract methods, I'm looking for a way to test the concrete method without having to manually subclass and implement all these methods. I was hoping to use a mock instance of the class somehow.


    • First failed attempt:

      # Without this, `AbstractFoo` cannot be instantiated.
      AbstractFoo.__abstractmethods__ = frozenset()

      mock_foo = unittest.mock.Mock(wraps=AbstractFoo())
      mock_foo.create_something.return_value = "bar"

      assert mock_foo.append_something("foo") == "foobar"
      mock_foo.create_something.assert_called_once_with(3)


      Even though I try to mock the create_something method return value, the NotImplementedError from AbstractFoo.create_something is raised when mock_foo.append_something("foo") is called.


    • Second failed attempt

      class MockFoo(AbstractFoo):
      def create_something(self, number: int) -> str:
      return "bar"

      MockFoo.__abstractmethods__ = frozenset()

      mock_foo = unittest.mock.Mock(wraps=MockFoo())
      mock_foo.create_something.side_effect = lambda *args, **kwargs: unittest.mock.DEFAULT

      assert mock_foo.append_something("foo") == "foobar"
      mock_foo.create_something.assert_called_once_with(3)


      This time I get:

      AssertionError: Expected 'create_something' to be called once. Called 0 times.

    Questions:


    1. In both of my failed attempts, the mock_foo.create_something mock does not seem to be used. Why's that?


    2. How can I test the append_something method of AbstractFoo without having to manually implement all the abstract methods of AbstractFoo in a dummy subclass?

    Continue reading...

Compartilhe esta Página