An extension for composing Mock's patch context manager.
It is not uncommon for multiple unit tests to require much of the same fixture setup. Many times, this just means the same types are mocked out for the scope of a unit test. Mock's context managers do not compose well, meaning you can't easily build up a list of patches. The purpose of multipatch is to allow you to easily build a context manager for composing patches and control their lifetimes.
Here is an example using multipatch:
from mock import patch from multpatch import multipatch from unittest import TestCase class Dependency1(object): def getNumber(self): return 1 class Dependency2(object): def getNumber(self): return 2 class SUT(object): def foo(self): dep1 = Dependency1() dep2 = Dependency2() return dep1.getNumber() + dep2.getNumber() class SUTTestCase(TestCase): def testFoo_mockDepsOnlyInCntx(self): sut = SUT() with multipatch( dep1=mock.patch('__main__.Dependency1'), dep2=mock.patch('__main__.Dependency2') ) as patcher: # reference dependencies by name patcher.dep1.getNumber.return_value = 3 patcher.dep2.getNumber.return_value = 4 result = sut.foo() # adds mocked return values self.assertEqual(7, result) result = sut.foo() # adds the original return values self.assertEqual(2, result)
The patch collection returned from multipatch can be returned from a function. New multipatches can be created by passing other multipatches to the
multipatch function. This means you can easily compose patches together. Instead of dealing with the tuples that
nest provides or with the one-and-done nature of
patch.multiple. You can access your mock objects by name and reuse patches via composition.
Multipatches can also be used anywhere a
patch can be used, except as a decorator. This means if you want to merge two multipatches with conflicting mock names, you can just make one of the multipatches a patch by giving it a name:
def getPatches(): nested = multipatch(class1=patch('package.module.ClassName1')) patch = multipatch(nested=nested, class1=patch('package.module.ClassName2')) # patch.nested.class1