如何使用装饰器修补sys属性?

时间:2018-10-22 11:34:57

标签: python python-3.x mocking python-unittest

我有一个依赖于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_func时,if sys.version_info[0] < 3失败。

1 个答案:

答案 0 :(得分:1)

编辑:

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

Edit2:

正如Zaur Nasibov指出的,sys.version_info不是一个函数,因此尽管使用模拟程序看起来不错,但我的代码还是错误的(GenError也发现了)。我进行了一些小的更改以解决此问题(有关使用PropertyMock的替代方法,请参见GenError答案)

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.