Python 的模拟测试介绍(6)

陷阱:mock.Mock和mock.MagicMock类

mock库包含两个重要的类mock.Mock和,大多数内部函数都是建立在这两个类之上的。在选择使用mock.Mock实例,mock.MagicMock实例或auto-spec方法的时候,通常倾向于选择使用 auto-spec方法,因为它能够对未来的变化保持测试的合理性。这是因为mock.Mock和mock.MagicMock会无视底层的API,接受所有的方法调用和参数赋值。比如下面这个用例:

class Target(object):
    def apply(value):
        return valuedef method(target, value):
    return target.apply(value)

我们像下面这样使用mock.Mock实例来做测试:

class MethodTestCase(unittest.TestCase):

def test_method(self):
        target = mock.Mock()

method(target, "value")

target.apply.assert_called_with("value")

这个逻辑看似合理,但如果我们修改Target.apply方法接受更多参数:

class Target(object):
    def apply(value, are_you_sure):
        if are_you_sure:            return value        else:            return None

重新运行你的测试,然后你会发现它仍然能够通过。这是因为它不是针对你的API创建的。这就是为什么你总是应该使用create_autospec方法,并且在使用@patch和@patch.object装饰方法时使用autospec参数。

真实世界的例子: 模仿一次 Facebook API 调用

在结束之际,让我写一个更加实用的真实世界的例子, 这在我们的介绍部分曾今提到过: 向Facebook发送一个消息. 我们会写一个漂亮的封装类,和一个产生回应的测试用例.

import facebookclass SimpleFacebook(object):
   
    def __init__(self, oauth_token):
        self.graph = facebook.GraphAPI(oauth_token)    def post_message(self, message):
        """Posts a message to the Facebook wall."""
        self.graph.put_object("me", "feed", message=message)

下面是我们的测试用例, 它检查到我发送了信息,但并没有实际的发送出这条信息(到Facebook上):

import facebookimport simple_facebookimport mockimport unittestclass SimpleFacebookTestCase(unittest.TestCase):
   
    @mock.patch.object(facebook.GraphAPI, 'put_object', autospec=True)
    def test_post_message(self, mock_put_object):
        sf = simple_facebook.SimpleFacebook("fake oauth token")
        sf.post_message("Hello World!")        # verify
        mock_put_object.assert_called_with(message="Hello World!")

就我们目前所看到的,在Python中用 mock 开始编写更加聪明的测试是真的很简单的.

总结

Python的 mock 库, 使用起来是有点子迷惑, 是单元测试的游戏规则变革者. 我们通过开始在单元测试中使用 mock ,展示了一些通常的使用场景, 希望这篇文章能帮助 Python 克服一开始的障碍,写出优秀的,能经得起测试的代码.

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/4f7480c272ffe8e2f9863c15b27b0b31.html