Package: pytest-when
pytest-whenInspired
bymokito-scala,pytest-whenprovides a fixture forpytestto simplify the mocking of python objects:PurposeMore readable than the fullGiven...When...Thenpattern,pytest-whenis
meant for developers who want to test for behaviour, without any extra
overhead.
Enable the mock only for a specific argument's values to make code more
readable.BenefitsIn this example, when you specify the first two arguments andanythird
argument, the attribute will be mocked,(when(some_object,"attribute").called_with(1,2,when.markers.any).then_return("attribute mocked"))Note that the.called_withmethod arguments are compared with the real
callable signature.
This gives additional protection against changing the real callable interface.Withwhenfixture, the following expression:when(example_module,"some_normal_function").called_with("a",1,kwarg1="b",kwarg2=2,).then_return("Mocked")is roughly equal to:mock_only_for_calls=(call("a",1,kwarg1="b",kwarg2=2),"Mocked",)defmatches(call:Call,mocked_calls_registry:tuple[tuple[call,ReturnType],...],)->bool:...defcreate_call(*args,**kwargs)->Call:...defside_effect_callback(*args,**kwargs):ifmatches(create_call(*args,**kwargs),mock_only_for_calls):returnmock_only_for_calls[1]returnunittest.mock.DEFAULTmocker.patch.object(example_module,"some_normal_function",autospec=True,side_effect=side_effect_callback,)where logic ofmatchesandcreate_callis not trivialInstallationInstall the package into your development environment, frompypi, usingpip, for example:pipinstallpytest-whenImplementationOnced installed, thewhenfixture will be available just like the rest of
thepytestplugins.
See the following example of how to use it:# class which we're going to mock in the testclassKlass1:defsome_method(self,arg1:str,arg2:int,*,kwarg1:str,kwarg2:str,)->str:return"some_method not mocked"deftest_should_properly_patch_calls(when):when(Klass1,"some_method").called_with("a",when.markers.any,kwarg1="b",kwarg2=when.markers.any,).then_return("some method mocked")assert(Klass1().some_method("a",1,kwarg1="b",kwarg2="c",)=="some method mocked")assert(Klass1().some_method("not mocked param",1,kwarg1="b",kwarg2="c",)=="some method not mocked")# if you need to patch a functiondeftest_patch_a_function(when):when(example_module,"some_normal_function").called_with("a",when.markers.any,kwarg1="b",kwarg2=when.markers.any,).then_return("some_normal_function mocked")assert(example_module.some_normal_function("a",1,kwarg1="b",kwarg2="c",)=="some_normal_function mocked")assert(example_module.some_normal_function("not mocked param",1,kwarg1="b",kwarg2="c",)=="some_normal_function not mocked")It is possible to usewhenwith class methods and standalone functions
(in this case cls parameter will become a python module).You can patch the same object multiple times using differentcalled_withparameters in a single test.You can also patch multiple targets (cls, method)See more examples at:test_integrationSetup for local developementThe project can be extended by cloning the repo and
installingthePDMbuild toolSo, the development environment requires:pdmhttps://pdm.fming.dev/latest/#installationpython3.8 or greaterpdminstallTo run tests and linters use:maketestmakelint