Python模拟中的模拟属性?


76

mock在Python中使用时遇到了一些困难:

def method_under_test():
    r = requests.post("http://localhost/post")

    print r.ok # prints "<MagicMock name='post().ok' id='11111111'>"

    if r.ok:
       return StartResult()
    else:
       raise Exception()

class MethodUnderTestTest(TestCase):

    def test_method_under_test(self):
        with patch('requests.post') as patched_post:
            patched_post.return_value.ok = True

            result = method_under_test()

            self.assertEqual(type(result), StartResult,
                "Failed to return a StartResult.")

测试实际上返回正确的值,但r.ok它是Mock对象,不是True。您如何在Pythonmock库中模拟属性?

Answers:


92

您需要使用return_valuePropertyMock

with patch('requests.post') as patched_post:
    type(patched_post.return_value).ok = PropertyMock(return_value=True)

这意味着:调用时requests.post,在该调用的返回值上,PropertyMock为属性设置aok以返回value True


如果我从中print获得价值,我不会。r.okmethod_under_test<MagicMock name='post().ok' id='57360464'>True
纳夫图利凯13'May

@TKKocheran:我已经更新了答案。您还需要使用PropertyMock
Simeon Visser

13
为什么不使用simpy patched_post.return_value = mock.Mock(ok=True)
lumbric '16

3
@lumbric因为您可以PropertyMock用来断言它像任何其他Mock对象一样被访问。只给属性分配一个值就不能做到。
博诺

20

一种紧凑而简单的方法是使用new_callable patch的属性来强制patch使用PropertyMock而不是MagicMock创建模拟对象。传递给的其他参数patch将用于创建PropertyMock对象。

with patch('requests.post.ok', new_callable=PropertyMock, return_value=True) as mock_post:
    """Your test"""

15

使用模拟版本“ 1.0.1”时,问题中提到的更简单的语法受支持并按原样运行!

示例代码已更新(使用py.test代替unittest):

import mock
import requests


def method_under_test():
    r = requests.post("http://localhost/post")

    print r.ok

    if r.ok:
        return r.ok
    else:
        raise Exception()


def test_method_under_test():
    with mock.patch('requests.post') as patched_post:
        patched_post.return_value.ok = True

        result = method_under_test()
        assert result is True, "mock ok failed"

使用以下代码运行此代码:(确保您安装pytest)

$ py.test -s -v mock_attributes.py 
======= test session starts =======================
platform linux2 -- Python 2.7.10 -- py-1.4.30 -- pytest-2.7.2 -- /home/developer/miniconda/bin/python
rootdir: /home/developer/projects/learn/scripts/misc, inifile: 
plugins: httpbin, cov
collected 1 items 

mock_attributes.py::test_method_under_test True
PASSED

======= 1 passed in 0.03 seconds =================

这不能为问题提供答案。要批评或要求作者澄清,请在其帖子下方留下评论-您可以随时对自己的帖子发表评论,一旦拥有足够的声誉,您就可以在任何帖子中发表评论
philant 2015年

仅供参考,requests.post.ok是属性,而不是属性。如果您尝试使用简单对象whereok是简单属性,则问题中提到语法有效,但对于requests.post.ok对象no:它将引发AttributeError
米歇尔·达米科

@philant谢谢您的反馈,如示例所示,这是问题的最新答案,并且语法很简单。
howaryoo,2015年

@ Micheled'Amico感谢您的反馈,我尝试过请看一下;-)
howaryoo 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.