Python mock的基本使用介绍

控制你的数据——Python mock的基本使用

Mock是什么

Mock即模拟的意思。在Python中,提供了基于单元测试的mock模块,它的主要作用是使用mock对象替代掉指定的Python对象,以达到模拟对象功能的行为。

在单元测试实际项目中,会遇到如下问题:

  • 接口间的相互依赖
  • 数据库中真实数据的模拟
  • 第三方接口调用

但由于单元测试仅针对当前单元进行测试,这就要求所有的内部或者外部依赖都应该是稳定的,采用mock的方法模拟跟本单元依赖的其他单元,可以将测试重点放在当前单元功能,排除外界因素干扰,提升测试精准度。

Mock基本用法

Mock对象是mock模块中最重要的概念。Mock对象就是mock模块中的一个类的实例,这个类的实例可以用来替换其他的Python对象,来达到模拟的效果。Mock类的定义如下:

class Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, **kwargs)

可以看到,Mock对象其实就是Python的一个类。

mock模块在Python3中是集成在unittest模块中的,我们先看一个简单的例子,用来说明mock模块的基本用法。

比如获取天气信息接口:

import requests

def send_request(url):
    r = requests.get(url)
    return r.status_code

def get_notify():
    url = "http://notify.mse.sogou.com/weather?city=%E5%8C%97%E4%BA%AC"
    return send_request(url)

然后我们使用mock对象在单元测试中分别测试正常返回和异常返回的情况:

import unittest
from unittest import mock
import notify

class TestNotify(unittest.TestCase):

    def test_success_request(self):
        success_send = mock.Mock(return_value='200')
        notify.send_request = success_send
        self.assertEqual(notify.get_notify(),'200')

    def test_fail_request(self):
        fail_send = mock.Mock(return_value='404')
        notify.send_request = fail_send
        self.assertEqual(notify.get_notify(),'404')

通常情况下,Mock对象的一般用法是这样的:

1、确定要测试的函数,或者类,或者类实例,作为mock的对象;我们要测试的是get_notify这个函数,这个函数依赖于send_request这个函数,所以需要替换的是send_request这个函数。

2、实例化Mock类得到一个mock对象,并设置这个mock对象的行为,比如被调用的时候返回什么值,被访问成员的时候返回什么值等;通过return_value设置mock对象的返回值。

3、使用2中的mock对象,替换掉1中确定的对象;替换掉notify.send_request。

4、可以开始写测试代码,这个时候我们可以保证被替换掉的对象在测试用例执行过程中行为和我们预设的一样。

Mock静态方法

有些函数可能不属于你,你也不在意它的内部实现而只是想调用这个函数然后得到结果而已,这种时候就可以用 patch 方式来模拟。

如果调用的外部代码是面向过程的风格,也就是一个一个函数,那么就用 mock.patch 就可以;如果是面向对象的风格,比如你调用的只是一个类中的某个方法,那么要用 mock.patch.object 。

上述的单元测试案例,使用patch时需要注意,它是一个装饰器,需要把你想模拟的函数写在里面,然后在后面的单元测试案例中为它赋一个具体实例,再用 return_value 来指定模拟的这个函数希望返回的结果就可以了,后面就是正常单元测试代码。实现如下:

import unittest
from unittest import mock
import notify

class TestNotify(unittest.TestCase):
    
	def setUp(self):
        pass
    
    def tearDown(self):
        pass
    
    @mock.patch("notify.send_request")
    def test_success_request(self,mock_send_request):
        mock_send_request.return_value='200'
        self.assertEqual(notify.get_notify(),'200')
	
    @mock.patch("notify.send_request")
    def test_fail_request(self,mock_send_request):
        mock_send_request.return_value='404'
        self.assertEqual(notify.get_notify(),'404')

结束语

本文的主要目的是介绍mock能做什么,当你知道了mock能做什么之后,要如何学习并掌握mock呢?最好的方式就是查看阅读官方文档,并在自己的单元测试中熟练控制外部服务和依赖。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值