Usage

Making Classes Fakeable

In order for a class to be Fakeable, it must opt-in to this functionality by declaring fakeable.Fakeable as the metaclass. See the documentation for fakeable.Fakeable for details on how to declare a metaclass (it’s easy!). The “magic” of the metaclass is that before a new object of the class is created it first checks to see if a fake version has been registered; if a fake is found then it is returned instead of a new instance of the class; otherwise, a new instance of the class is created and returned as per usual.

Registering Fake Objects

When unit testing, a class can be replaced with a fake version by setting either an object or a class to be the fake replacement.

If an object is specified, via fakeable.set_fake_object(), then each time an instance of the fakeable class is created the registered object will be returned instead.

If a class is specified, via fakeable.set_fake_class(), then each time an instance of the fakeable class is requested a new instance of the fake class will be created and returned instead. Note that any arguments that would have otherwise been specified to the __init__() method of the fakeable class will be specified to the __init__() method of the fake class. This means that either the fake class’ __init__() method must have the same argument list as the real class or use “catch-all” arguments, such as __init__(self, *args, **kwargs).

If a fake object and a fake class are both registered for a particular class then the most-recently-registered one will be used. Each time a fake object or fake class is registered, it replaces any previously-registered fake classes or objects.

Fakeable Class Names

When a fake object is registered via fakeable.set_fake_object() or a fake class is registered via fakeable.set_fake_class() a name for the fake class must be specified.

By default, this name is a string whose value is the name of the class that is desired to be faked. For example, to use a fake version of the HttpDownloader class, specify the name "HttpDownloader". A fakeable class can override this default name by setting __FAKE_NAME__ in its class definition. If a class overrides the default fake name, then that value must be used instead of the default value. A class’ fake name, either the default value or overrided value, is always available via the __FAKE_NAME__ attribute of the class. For example, to discover the name to use when faking out the HttpDownloader class check the value of HttpDownloader.__FAKE_NAME__. Although __FAKE_NAME__ is normally a string object, it may technically be any hashable object, including int, float, and frozenset.

If two different classes happen to have the same name, the name can instead be the class object of the real class itself. For example, to use a fake version of the HttpDownloader class, specify the name as the HttpDownloader class.

If both the fakeable class’ name and class object are registered then the object or class registered with the class object will be used. This is because the fakeable.Fakeable class first checks to see if there is a fake registered against the class object. Only if no fake registered against the fakeable class does it check to see if one is registered against the name of the fakeable class.

The author of Fakeable generally recommends to use string names whenever possible. The reason is that this removes the need to import the real class in the unit tests, only to replace it with fake versions. That being said, using the class objects of the fakeable classes as names gives a degree of “type safety”, in that if the fakeable class is renamed, moved, or deleted an exception will be raised when the tests are run, pointing to tests that needs to be updated. No such error reporting occurs when string names are used. In the end, both facilities work equally well and it is up to the test author to choose which method is preferred.

Unregistering Fake Objects

There are three different ways to unregister a fake object:

  1. fakeable.unset()
  2. fakeable.clear()
  3. the context manager returned from fakeable.set_fake_object() or fakeable.set_fake_class()
  4. FakeableCleanupMixin

By invoking fakeable.unset() with the same name that was specified to either fakeable.set_fake_object() or fakeable.set_fake_class() it will cause the real class to once again produce real objects. It is good practice to perform a matching “unset” for each “set” to avoid using fake objects outside of the intended scope.

By invoking fakeable.clear() all registered fakes will be unregistered. This is equivalent to invoking fakeable.unset() for each registered fake. If using the built-in unittest module, it is a good idea to call fakeable.clear() in both setUp() and tearDown() to ensure a pristine fake environment and that no fake objects “leak” outside the unit test, respectively.

Both fakeable.set_fake_object() and fakeable.set_fake_class() return a context manager, which can be used in a with statement to automatically unregister the fake. For example:

with fakeable.set_fake_object("Number", 1):
    ...

In the code sample above, the fake object will be automatically unset when the “with” block is exited.

If using the unittest testing framework from the Python standard library you can use the FakeableCleanupMixin class to automatically unregister all fakes at the beginning and end of each test case. This is especially useful to avoid fakes accidentally remaining registered after the test completes. To use FakeableCleanupMixin, simply make your unit test case classes inherit from both unittest.TestCase and FakeableCleanupMixin. This will add setUp() and tearDown methods to the test class which invoke fakeable.clear() before and after your test, respectively. See the documentation for FakeableCleanupMixin for details.

Project Versions

Table Of Contents

Previous topic

Simple Example

Next topic

API Reference

This Page