I have the following method:
class Controls: def check_os(self) -> None: if os.name != "posix": raise OSError
I’m trying to test it like this:
import pytest @pytest.fixture def name_mock(mocker): return mocker.patch("path_to_module.controls.os.name", return_value="posix") def test_check_os_fail(name_mock): controls = Controls() controls.check_os()
But then the following error is raised:
platform win32 -- Python 3.9.0, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 plugins: cov-2.11.1, mock-3.5.1 collected 57 items / 56 deselected / 1 selected teststest_controls.py INTERNALERROR> Traceback (most recent call last): ... NotImplementedError: cannot instantiate 'PosixPath' on your system
What is happening exactly?
Advertisement
Answer
What is happening here is that pytest
internally uses a pathlib.Path
object, which upon initialization asks for os.name
to define which Path
implementation to use. There are two internal implementations for Path
, PosixPath
and WindowsPath
, which are only available under the respective systems. As you are faking a Posix system by patching os.name
, it tries to instantiate a PosixPath
object, which is not defined under Windows.
What you can do in this case is to wrap os.name
in your own function, e.g. something like:
import os def os_name(): return os.name class Controls: def check_os(self) -> None: if os_name != "posix": raise OSError
and patch that function in your test:
@pytest.fixture def name_mock(mocker): return mocker.patch("path_to_module.controls.os_name", return_value="posix")
This way you only patch the call you are supposed to patch, without affecting other code that also uses os.name
.