首页 > 解决方案 > 无法在 Windows 上使用 Python 模拟操作系统名称

问题描述

我有以下方法:

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

究竟发生了什么?

标签: pythonunit-testingmockingpytest

解决方案


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

在这种情况下,您可以做的是包装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.


推荐阅读