【问题标题】:Unable to mock os name with Python on Windows无法在 Windows 上使用 Python 模拟操作系统名称
【发布时间】:2021-07-18 22:23:52
【问题描述】:

我有以下方法:

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

到底发生了什么?

【问题讨论】:

    标签: python unit-testing mocking pytest


    【解决方案1】:

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

    在这种情况下,您可以将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的其他代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-25
      • 1970-01-01
      • 1970-01-01
      • 2015-05-25
      • 1970-01-01
      • 2023-02-04
      • 1970-01-01
      相关资源
      最近更新 更多