A metaclass to be used by types that wish to be fakeable.
In order to make a class fakeable, all that needs to be done is set fakeable.Fakeable as its metaclass. In Python 2, this done by setting the special attribute __metaclass__ = fakeable.Fakeable in the class definition. In Python 3, this is done by specifying metaclass=fakeable.Fakeable in the base class list of the class definition.
Python 2 example:
class HttpDownloader(object):
__metaclass__ = fakeable.Fakeable
...
Python 3 example:
class HttpDownloader(metaclass=fakeable.Fakeable):
...
If you have the third-party six module installed, then you can do this in a way that works in both Python 2 and Python 3:
class HttpDownloader(six.with_metaclass(fakeable.Fakeable)):
...
The name used in the fakeable module functions to refer to this class is simply the name of the class. This value is stored in the __FAKE_NAME__ attribute of the class. If a class explicitly defines a __FAKE_NAME__ attribute then that value will be used instead of the default.
Configures the class with the given name to create fake objects instead of real objects when created. When an instance of the class of the given name is created a new instance of the given type will be created instead.
Returns a context manager that can be used as the target of a “with” statement; when the context of the “with” statement is exited the fake class will be automatically unregistered by a call to self.unset(name).
Configures the class with the given name to always use a fake object instead of real objects when created. When an instance of the class of the given name is created the given value will be returned instead.
Returns a context manager that can be used as the target of a “with” statement; when the context of the “with” statement is exited the fake object will be automatically unregistered by a call to self.unset(name).
Unregisters a fake that was registered by a previous invocation of set_fake_object() or set_fake_class().
Returns True if a fake was indeed registered with the given name and was successfully unregistered. Returns False if a fake was not registered with the given name and therefore this function did nothing.
Registers a callback to be invoked each time an instance of a Fakeable class is created. The given callback will invoked each time that a class with the Fakeable metaclass is created, whether it returns a fake object or a new instance of the real class. This can be useful during unit testing to examine the objects created by a third-party after the fact.
No checking for duplicate callback registrations is performed; therefore, if a given callback is registered twice then it will be invoked twice each time that an instance of a Fakeable class is created.
Callbacks are invoked synchronously, and in the order in which they are added. No exception handling is performed around the callbacks; therefore, if a callback raises an exception it will trickle up the call stack until it is either caught or falls of the end, aborting the program. This will also prevent the other callbacks from receiving the notification.
Callbacks may be unregistered by remove_created_callback() (to unregister a specific callback) or clear() (to unregister all callbacks).
Unregisters a callback that was registered by a previous invocation of add_created_callback(). If the given callback is registered more than once then only one of its registrations will be removed. Therefore, to fully unregister a callback there must be one call to this function for each call to add_created_callback().
Returns True if the given callback was found in the list of registered callbacks and was removed; returns False if the given callback was not found in the list of registered callbacks and therefore this method did nothing.
A convenience class that can be inherited by unit test classes so that fakes are automatically cleaned up before and after each test runs. This helps prevent fake objects inadvertently leaking into other test cases, which can cause difficult-to-diagnose behaviour when it happens.
This class is intended to be subclassed by other classes that also inherit from unittest.TestCase. It defines setUp() and tearDown(), both of which simply invoke fakeable.clear() and the method of the same name in the superclass.
Example: using this “mixin” class in a unittest.TestCase:
class TestSomething(fakeable.FakeableCleanupMixin, unittest.TestCase):
def test(self):
fakeable.set_fake_class("Something", FakeSomething)
self.assertTrue(do_something())
Before the method test() is executed the setUp() method will invoke fakeable.clear() to make sure there are no leftover fakes that were registered elsewhere. Also, after the test() method completes, tearDown() will invoke fakeable.clear() to make sure that none of the registered fakes are left behind to screw things up downstream.
Note, however, that fakeable.FakeableCleanupMixin must occur before unittest.TestCase in the base class list. Otherwise, the setUp() and tearDown() methods of FakeableCleanupMixin will not be invoked.
Bad Example (of specifying base classes of a test case):
# BAD!! -- because unittest.TestCase is specified *before*
# fakeable.FakeableCleanupMixin in the base class list,
# the setUp() and tearDown() methods of FakeableCleanupMixin will not
# be invoked, defeating the purpose of adding it as a base class
class TestSomething(unittest.TestCase, fakeable.FakeableCleanupMixin):
...
Good Example (of specifying base classes of a test case):
# GOOD -- because unittest.TestCase is specified *after*
# fakeable.FakeableCleanupMixin in the base class list,
# the setUp() and tearDown() methods of FakeableCleanupMixin *will*
# be invoked, properly unregistering all registered fakes
class TestSomething(fakeable.FakeableCleanupMixin, unittest.TestCase):
...
If the FakeableCleanupMixin subclass also wants to override setUp() and/or tearDown(), be sure to use the super() built-in to call the method of the same name in the superclass (as opposed to naming the superclass and calling it directly). Using super() ensures that the method-resolution order (“mro”) will be used and each superclass’ method will be invoked in the correct order.
Bad Example (of overriding the setUp() method):
class TestSomething(fakeable.FakeableCleanupMixin, unittest.TestCase):
def setUp(self):
# BAD!! -- does not respect the MRO and some superclass setUp()
# methods may not be invoked
fakeable.FakeableCleanupMixin.setUp(self)
...
Good Example (of overriding the setUp() method):
class TestSomething(fakeable.FakeableCleanupMixin, unittest.TestCase):
def setUp(self):
# GOOD -- respects the MRO and ensures that the setUp() method
# of each superclass is invoked and in the correct order
super(TestSomething, self).setUp()
...
Invokes the setUp method of the superclass, and then fakeable.clear(). This ensures that fakes that have been previously set do not leak into tests.
Invokes fakeable.clear() and then the tearDown() method of the superclass. This ensures that fakes that have been set in tests do not leak into other tests. It also precludes the need to explicitly unregister fake objects.