How does @ mock.patch know which option to use for each layout?

Looking at this web page: http://www.toptal.com/python/an-introduction-to-mocking-in-python - the author talks about Mocking and Patching in Python and gives a pretty solid "real world" "example. The part that turns me off is to understand how the block checks the operation of the block, which layout of the object is transferred to which patch.

#!/usr/bin/env python # -*- coding: utf-8 -*- import os import os.path def rm(filename): if os.path.isfile(filename): os.remove(filename) 

Sample code is pretty easy to understand. Hard-coded library / OS module dependency. First, it checks to see if the file exists using the os.path.isfile() method, and if so, deletes it using os.remove()

The test / layout code is as follows:

 #!/usr/bin/env python # -*- coding: utf-8 -*- from mymodule import rm import mock import unittest class RmTestCase(unittest.TestCase): @mock.patch('mymodule.os.path') @mock.patch('mymodule.os') def test_rm(self, mock_os, mock_path): # set up the mock mock_path.isfile.return_value = False rm("any path") # test that the remove call was NOT called. self.assertFalse(mock_os.remove.called, "Failed to not remove the file if not present.") # make the file 'exist' mock_path.isfile.return_value = True rm("any path") mock_os.remove.assert_called_with("any path") 

I assume that it confuses me that in the test there are 2 calls @Patch and 2 parameters. How does the module testing platform know that mymodule.os.path fixes os.path and that it maps to mock_path ? Where is mymodule.os.path defined?

(It seems that "magic" is happening, and I am not following it.)

+5
python unit-testing mocking
source share
2 answers

this happens in order of execution of decorators, as well as in order of parameters passed to your test method ...

the order of execution of the decorators is shown here: https://thadeusb.com/weblog/2010/08/23/python_multiple_decorators/

When you use patch as you wrote it, a Mock instance is automatically created for you and passed as a parameter to your test method. there is another version of this:

 @mock.patch("subprocess.check_output", mock.MagicMock(return_value='True')) def test_mockCheckOutput(self): self.assertTrue(subprocess.check_output(args=[])=='True') 

in this case, you pass your own Mock object, and in this example, when you call subprocess.check_output (), it returns "True"

however you could do:

 def test_mockCheckOutput(self): m = mock.MagicMock(return_value='True') with mock.patch("subprocess.check_output", m): self.assertTrue(subprocess.check_output(args=[])=='True') 

and in this case, you can pass any layout element that you want, because it will be evaluated at runtime ... :)

+3
source share

When applying a decorator, it’s good to look at it as

 <wrapper1> <wrapper2> <wrapper3> **Your Function** </wrapper3> </wrapper2> </wrapper1> 

Basically, your function should interact with wrappers in the following order:

wrapper3 β†’ wrapper2 β†’ wrapper1

 @wrapper1 @wrapper2 @wrapper3 def your_func(wrapper1.input, wrapper2.input, wrapper3.input): 

NOTE. wrapper1.input is not how you really refer to your input

To answer the second part of your question, how mymodule.os knows you need to reference os. With Patching, you actually intercept calls to that particular name. When you call os in mymodule , you actually call mymodule.os . When correcting, you should refer to the class, which is ridiculed by the way it is called in the actual code, and not from the point of view of test modules.

+1
source share

All Articles