首页 > 解决方案 > 如何使用装饰器修补 sys 属性?

问题描述

我有一个取决于 Python 版本的函数。我想通过模拟sys.version信息在单元测试中对此进行测试。以下代码有效:

def test_python_version(self):
    with patch("sys.version_info", [3]):
        my_func()
    with patch("sys.version_info", [2]):
        my_func()

我想使用装饰器,但以下代码不起作用。为什么是这样?如何设置传递给我的测试的 MagicMock 对象的值?谢谢

@patch("sys.version_info")
def test_python_version(self, mock_version_info):
        mock_version_info.return_value = [3]
        my_func()
        mock_version_info.return_value = [2]
        my_func()

尝试做TypeError: '<' not supported between instances of 'MagicMock' and 'int'时失败。my_funcif sys.version_info[0] < 3

标签: pythonpython-3.xmockingpython-unittest

解决方案


编辑:

是的,它有效。原始函数返回一个带有major,minormicro字段的命名元组。您可以通过构建自己的命名元组来模仿它。当您使用int索引访问时,我只是使用一个简单的元组。您的代码的问题在于您索引的方式[0]不正确。

编辑2:

正如 Zaur Nasibov 指出的那样,sys.version_info它不是一个函数,因此尽管在模拟中看起来不错(正如 GenError 也发现的那样),但我的代码是错误的。我做了一些改动来修复它(请参阅 GenError 答案以获取替代方法PropertyMock

import sys
from unittest.mock import patch

def my_func():
    version = sys.version_info # removed the ()
    print('Detected version:', version)
    if version[0] < 3:
        print('Error: Python 3 required.')

@patch('__main__.sys')
def test_python_version(mock_sys):
        mock_sys.version_info = (3,6,2)
        my_func()
        print()
        mock_sys.version_info = (2,7,0)
        my_func()


test_python_version()

输出

Detected version: (3, 6, 2)

Detected version: (2, 7, 0)
Error: Python 3 required.

推荐阅读