Skip to content
Advertisement

Unable to mock os name with Python on Windows

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.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement