Python mock
在测试过程中,为了更好地展开单元测试,mock一些数据跟对象在所难免,下面讲一下python的mock的简单用法。
关于python mock,网上有很多资料,这里不会讲的特别深,但一定会是实用为主,看完后,至少可以让你知道mock是怎样用的。
1.mock对象方法中的返回数据:
我们经常会需要这样的场景,a系统跟b系统联调,b系统开发人员进度较慢,有些a需要调用b系统api的返回数据没办法拿到,这时候,不改变原来的代码,但联调需要保证a系统这边功能完全ok
的场景就可以用到mock这个模块了。
在这里,我们假设b系统完成时是以下这个样子
system_b.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import json import requests def send_request(url): r = requests.get(url) return json.loads(r.text) def visit_ustack(): return send_request('http://api.kanzhihu.com/getposts') if __name__ == '__main__': content = visit_ustack() print content
我们通过调用visit_ustack()这个入口,可以得到http://api.kanzhihu.com/getposts这个接口返回的json数据。理想测试情况下,a系统这边的测试代码是这样的
system_a.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import system_b def system_b_test(): if system_b.visit_ustack()['count'] == 10: print "system b正常,测试通过" else: print "system b异常,测试失败" system_b_test()
结果显而易见是这样的
/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python /Users/lsf/PycharmProjects/py_pattern/test.py
system b正常,测试通过
Process finished with exit code 0
但现在糟糕的是,系统 b的主体函数send_request还没开发,我们没办法获取json格式的数据,当然,现实中可以通过很多其他的办法来解决,但为了最大程度仿真b系统,现在可以通过mock来完成这项工作。
现实中功能未完成的a系统
system_a.py
#!/usr/bin/env python # -*- coding: utf-8 -*- def send_request(url): pass def visit_ustack(): return send_request('http://api.kanzhihu.com/getposts') if __name__ == '__main__': content = visit_ustack() print content
system_b.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import mock import system_b def system_b_test(): mock_result = {u'count': 1000, u'publishtime': u'1470798000', u'date': u'2016-08-10', u'id': u'2375'}], u'error': u''} system_b.send_request = mock.Mock(return_value=mock_result) if system_b.visit_ustack()['count'] == 1000: print "system b正常,测试通过" else: print "system b异常,测试失败" system_b_test()
结果是
/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python /Applications/PyCharm.app/Contents/helpers/pycharm/utrunner.py /Users/lsf/PycharmProjects/py_pattern/test.py true Testing started at 15:24 ... system b正常,测试通过 Process finished with exit code 0 Empty test suite.
在这里,我们通过直接mock一个json数据,来达到b系统返回数据的目的,甚至我们调用的依然是b系统的接口,区别已用红色字体标出,这个就是mock的操作了。
(1)mock_result:准备需要的mock数据
(2)用mock.Mock(return_value=mock_result)将mock对象设置给系统b对应的返回方法中
值得注意的是,mock.Mock(return_value=mock_result)是一个对象,但为什么system_b.send_request = mock.Mock(return_value=mock_result)返回的是数据而不是对象的其他属性跟方法呢,在这里,是因为mock对象中有一个side_effect属性,如果这个属性为None,就会将return_value设置的值返回。
2.mock对象中的方法:mock.patch跟mock.patch.object
#!/usr/bin/env python # -*- coding: utf-8 -*- import mock class By(object): def add(self, a, b): return a + b + self.multiply(a,b) def multiply(self, a, b): pass b = By() class MockDemo(object): def __init__(self): self.b = b @mock.patch.object(b,'multiply') def test_add(self,mock_multiply): a = 3 b = 5 mock_multiply.return_value = 15 if self.b.add(a,b) == 23: print "mock成功" else: print "mock失败" if __name__ == '__main__': MockDemo().test_add()
如果mock的是一个函数,则可以用@mock.patch(target='module.func')来实现。