mock.create_autospec ?方法为类提供了一个同等功能实例.实际上来说,这意味着在使用返回的实例进行交互的时候,如果使用了非法的方式将会引发异常.更具体地说,如果一个方法被调用时的参数数目不正确,将引发一个异常.这对于重构来说是非常重要.当一个库发生变化的时候,中断测试正是所期望的.如果不使用 auto-spec,尽管底层的实现已经被破坏,我们的测试仍然会通过.
陷阱:mock.Mock 和 mock.MagicMock 类
mock ?库包含了两个重要的类?mock.Mock[5]?和?mock.MagicMock[6],大多数内部函数都是建立在这两个类之上的.当在选择使用?mock.Mock ?实例、mock.MagicMock ?实例还是 auto-spec 的时候,通常倾向于选择使用 auto-spec,因为对于未来的变化,它更能保持测试的健全.这是因为?mock.Mock ?和?mock.MagicMock ?会无视底层的 API,接受所有的方法调用和属性赋值.比如下面这个用例:
class Target(object):
? ?def apply(value):
? ? ? ?return value
def 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 facebook
class 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)
这是我们的测试用例,它可以检查我们发布的消息,而不是真正地发布消息:
import facebook
import simple_facebook
import mock
import unittest
class 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 总结
即使对它的使用还有点不太熟悉,对单元测试[7]来说,Python的mock库可以说是一个规则改变者.我们已经演示了常见的用例来了解了mock在单元测试中的使用,希望这篇文章能够帮助Python开发者[8]克服初期的障碍,写出优秀、经受过考验的代码.
via:https://www.toptal.com/python/an-introduction-to-mocking-in-python
作者:NAFTULITZVIKAY[9]译者:cposture[10]校对:wxy[11]
(编辑:ASP站长网)
|