Oto co znalazłem: Jeśli ustawisz atrybut __abstractmethods__
być zbiorem pustym będzie można utworzyć wystąpienia klasy abstrakcyjnej. Takie zachowanie jest określona w PEP 3119:
Jeśli uzyskany __abstractmethods__
zbiór jest niepusty, klasa jest uważany za streszczenie i próbuje oznacz ją podniesie TypeError.
Po prostu wyczyść ten atrybut na czas trwania testów.
>>> import abc
>>> class A(metaclass = abc.ABCMeta):
... @abc.abstractmethod
... def foo(self): pass
Cant instancji:
>>> A()
Traceback (most recent call last):
TypeError: Can't instantiate abstract class A with abstract methods foo
Jeśli zastąpić __abstractmethods__
można:
>>> A.__abstractmethods__=set()
>>> A() #doctest: +ELLIPSIS
<....A object at 0x...>
To działa w obie strony:
>>> class B(object): pass
>>> B() #doctest: +ELLIPSIS
<....B object at 0x...>
>>> B.__abstractmethods__={"foo"}
>>> B()
Traceback (most recent call last):
TypeError: Can't instantiate abstract class B with abstract methods foo
Można również użyć unittest.mock
(z 3.3), aby tymczasowo obejść zachowanie ABC.
>>> class A(metaclass = abc.ABCMeta):
... @abc.abstractmethod
... def foo(self): pass
>>> from unittest.mock import patch
>>> p = patch.multiple(A, __abstractmethods__=set())
>>> p.start()
{}
>>> A() #doctest: +ELLIPSIS
<....A object at 0x...>
>>> p.stop()
>>> A()
Traceback (most recent call last):
TypeError: Can't instantiate abstract class A with abstract methods foo
Cool. Spróbuję bawić się tym kodem w niektórych moich testach :). Dzięki! – bow