mock/patch os.path.exists with multiple return values
So after a bit more research and trial and error, with most of the examples here: http://www.voidspace.org.uk/python/mock/patch.html, I solved my problem.
import mock
import os
def side_effect(arg):
if arg == 1:
return True
else:
return False
class TestClass(unittest.TestCase):
patcher = mock.patch('os.path.exists')
mock_thing = patcher.start()
mock_thing.side_effect = side_effect
arg_list = [1, 2]
ret = test(arg_list)
self.assertItemsEqual([1], ret)
test
calls os.path.exist
for each item in arg_list
, and returns a list of all items that os.path.exist
returned True
for. This test now passes how I want it.
Yep_It's_Me
I've been working as a web developer since 2014 and have recently join HyraIQ as a co-founder.
Updated on June 05, 2022Comments
-
Yep_It's_Me almost 2 years
I'm trying to test a function that I made that iterates through a list, and calls
os.path.exists
for each item in the list. My test is passing the function a list of 2 objects. I needos.path.exists
to returnTrue
for one of them andFalse
for the other. I have tried this:import mock import os import unittest class TestClass(unittest.TestCase): values = {1 : True, 2 : False} def side_effect(arg): return values[arg] def testFunction(self): with mock.patch('os.path.exists') as m: m.return_value = side_effect # 1 m.side_effect = side_effect # 2 arglist = [1, 2] ret = test(argList)
Using either but not both of line #1 and #2 give
NameError: global name 'side_effect' is not defined
I found this question and modified my code like so:
import mock import os class TestClass(unittest.TestCase): values = {1 : True, 2 : False} def side_effect(arg): return values[arg] def testFunction(self): mockobj = mock(spec=os.path.exists) mockobj.side_effect = side_effect arglist = [1, 2] ret = test(argList)
And this produces
TypeError: 'module' object is not callable
. I also tried switching these lines:mockobj = mock(spec=os.path.exists) mockobj.side_effect = side_effect
for this
mockobj = mock(spec=os.path) mockobj.exists.side_effect = side_effect
and this
mockobj = mock(spec=os) mockobj.path.exists.side_effect = side_effect
with the same error being produced. Can anyone point out what it is that I am doing wrong and what I can do to get this to work?
EDIT: After posting my answer below I realised that my first bit of code actually works as well, I just needed
m.side_effect = TestClass.side_effect
instead ofm.side_effect = side_effect
. -
hithwen about 10 yearsAnd what if the function has the same argument on both calls?
-
Yep_It's_Me about 10 yearsWhat do you mean? If
os.path.exists
is passed a 1 for both calls? Then it will return True because that's what the side effect says. But it won't be passed the same arg twice because thetest
function iterates througharg_list
and callsos.path.exists
for each element in the list. So as long as both elements in the list aren't1
then it will work as expected. -
hithwen about 10 yearsI meant, if I want to call os.path.exists two times with the same argument and return first False and then True. I figured out how to do it defining a function that will count how many times have been called and returning different values and using it as a side_effect.