I am trying to modify a test to handle both Linux and Windows. The code being tested uses os.pathsep
. Example:
def path_split(pth):
if os.pathsep in pth:
return pth.split(os.pathsep)
else:
return [pth]
If I run the following test on Linux using a colon, it works:
class PathsepTest(TestCase):
def test_path_split(self):
result = path_split("foo:bar")
assert result == ["foo", "bar"]
However, if I try to mock os.pathsep
to return the Windows path separator (;
)
class PathsepTest(TestCase):
def test_path_split(self):
windows_pathsep = ";"
with patch.object(os, "pathsep", return_value=windows_pathsep):
result = path_split("foo;bar")
assert result == ["foo", "bar"]
it fails with
def path_split(pth):
> if os.pathsep in pth:
E TypeError: 'in <string>' requires string as left operand, not MagicMock
For a simpler function
def get_pathsep():
return os.pathsep
the corresponding test fails if I do
def test_get_pathsep(self):
windows_pathsep = ";"
with patch.object(os, "pathsep", return_value=windows_pathsep):
result = get_pathsep()
assert result == windows_pathsep
but passes if I do
assert result.return_value == windows_pathsep
Any suggestions would be welcome.
mock.patch
replace an object by another, default is to replace with a MagicMock
.
So patch.object(os, "pathsep", return_value=":")
, replace os.pathsep
by a MagicMock
. Then return_value
specify the behavior when you call the mock object (ie. os.pathsep.__call__
)
>>> with mock.patch("os.pathsep", return_value=";"):
... print(os.pathsep()) # os.pathsep has been replaced by a callable
...
;
But os.pathsep
isn't a callable object, it is str
. According to the documentation, you can simply replace the orginal object by another with the new
argument:
>>> with mock.patch("os.pathsep", new=";"):
... print(os.pathsep)
...
;