首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python :模拟一个属性还是模拟整个类?

Python :模拟一个属性还是模拟整个类?
EN

Stack Overflow用户
提问于 2018-07-28 01:11:46
回答 1查看 843关注 0票数 1

我尝试在以下业务代码中模拟Popen实例:

代码语言:javascript
复制
process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
output = process.communicate()[0]
if process.returncode != 0:

这是我的测试代码设置:

代码语言:javascript
复制
@mock.patch('subprocess.Popen.returncode')
@mock.patch('subprocess.Popen.communicate')
def testCommandExecutesCommunicate(self, mock_popen_communicate, mock_popen_returncode):

我也尝试过:

代码语言:javascript
复制
@mock.patch('subprocess.Popen.returncode')
@mock.patch('subprocess.Popen.communicate')
def testCommandExecutesCommunicate(self, mock_popen_communicate, mock_popen_returncode):

在这两种情况下,我都会收到returncode模拟的错误

代码语言:javascript
复制
Error
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 329, in run
    testMethod()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mock/mock.py", line 1297, in patched
    arg = patching.__enter__()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mock/mock.py", line 1369, in __enter__
    original, local = self.get_original()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mock/mock.py", line 1343, in get_original
    "%s does not have the attribute %r" % (target, name)
AttributeError: <class 'subprocess.Popen'> does not have the attribute 'returncode'

我应该如何模拟Popen?我应该以某种方式模仿Popen类吗?或者,通过模拟方法+属性,我走上了正确的道路?

EN

回答 1

Stack Overflow用户

发布于 2018-07-28 06:17:03

` `AttributeError:没有'returncode‘属性

看看subprocess.py上的代码,

代码语言:javascript
复制
class Popen():
    def __init__(self, ....):
        self.returncode = None

属性returncode__init__设置,然后由communicate()等更新,类属性returncode不是模拟友好的,因此会导致错误

为什么mockp.communicate() mockp.communicate.return_value = '123‘

mockp.communicate或with ()mockp.communicate = mock.Mock()相同,后者是为函数communicate创建新模拟对象的一种方式

mock.communicate.return_value = list([2, 3])用于设置模拟函数的return_value。

解决方案:我对这个解决方案并不完全满意,但我倾向于认为mock整个类的‘Popen()’是进行单元测试的方法。

对于单元测试,只需模拟整个类,模拟subprocess.Popen,设置returncodecommunicate(),并设置return_value,例如

remove_file.py

代码语言:javascript
复制
def do_cmd(command):
    process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
    exit_code = process.communicate()[0]
    return exit_code

test_remove_file.py

代码语言:javascript
复制
class TestDoCmd(unittest.TestCase):

    @mock.patch('remove_file.subprocess.Popen')
    def test_do_cmd(self, mockp):
        # add function
        mockp.returncode.return_value = 'abc'
        mockp.communicate()
        mockp.communicate.return_value = '123'
        file = '/tmp/none.txt'
        remove_file.do_cmd('rm -f {}'.format(file))
        mockp.assert_called_with('rm -f /tmp/none.txt', shell=True, stdout=-1)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51562651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档