无法在 Windows 上使用 Python 模拟 os 名称

Unable to mock os name with Python on Windows

我有以下方法:

class Controls:

    def check_os(self) -> None:

        if os.name != "posix":
            raise OSError

我正在尝试这样测试它:

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()

但随后出现以下错误:

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

tests\test_controls.py 
INTERNALERROR> Traceback (most recent call last):
...
NotImplementedError: cannot instantiate 'PosixPath' on your system

到底发生了什么?

这里发生的是 pytest 内部使用 pathlib.Path 对象,该对象在初始化时要求 os.name 定义要使用的 Path 实现。 PathPosixPathWindowsPath有两种内部实现,只在各自的系统下可用。当您通过修补 os.name 伪造 Posix 系统时,它会尝试实例化 PosixPath 对象,该对象未在 Windows.

下定义

在这种情况下你可以做的是将 os.name 包装在你自己的函数中,例如类似于:

import os

def os_name():
    return os.name

class Controls:
    def check_os(self) -> None:
        if os_name != "posix":
            raise OSError

并在您的测试中修补该功能:

@pytest.fixture
def name_mock(mocker):
    return mocker.patch("path_to_module.controls.os_name", return_value="posix")

这样你只修补你应该修补的调用,而不影响其他也使用 os.name.

的代码