温嘉玲 發表於 2019-6-26 18:29:00

python接口自动化之mock模块基本使用

<h3>mock简介</h3>
<p>mock原是python的第三方库</p>
<p>python3以后mock模块已经整合到了unittest测试框架中,不用再单独安装</p>
<p>Mock这个词在英语中有模拟的意思,因此我们可以猜测出这个库的主要功能是模拟一些东西</p>
<p>准确的说,Mock是Python中一个用于支持单元测试的库,它的主要功能是使用mock对象替代掉指定的Python对象,以达到模拟对象的行为</p>
<p>既然mock已经被整合到了unittest单元测试框架中,可想而知mock的目的就是为了让我们更好的进行测试</p>
<h3>mock作用</h3>
<p>1. 解决依赖问题:当我们测试一个接口或者功能模块的时候,如果这个接口或者功能模块依赖其他接口或其他模块,那么如果所依赖的接口或功能模块未开发完毕,那么我们就可以</p>
<p>使用mock模拟被依赖接口,完成目标接口的测试</p>
<p>2. 单元测试:如果某个功能未开发完成,我们又要进行测试用例的代码编写,我们也可以先模拟这个功能进行测试</p>
<p>3. 模拟复杂业务的接口:实际工作中如果我们在测试一个接口功能时,如果这个接口依赖一个非常复杂的接口业务,那么我们完全可以使用mock来模拟这个复杂的业务接口,其实</p>
<p>这个和解决接口依赖是一样的原理</p>
<p>4.前后端联调:如果你是一个前端页面开发,现在需要开发一个功能:根据后台返回的状态展示不同的页面,那么你就需要调用后台的接口,但是后台接口还未开发完成,是不是你</p>
<p>就停止这部分工作呢?答案是否定的,你完全可以借助mock来模拟后台这个接口返回你想要的数据</p>
<h3>mock安装</h3>
<p>python 3 的mock模块已经被整合到了unittest框架中,所以你使用的时候只需要在文件开头from unittest import mock 导入即可</p>
<p>如果你使用的是python2 那么你需要执行pip install mock安装后再 import mock即可</p>
<h3>mock实例</h3>
<h4>一个未开发完成的功能如何测试?</h4>
<p>假如们现在有一个实现两个数相加的功能需要编写测试用例,但是由于开发进度缓慢,只搭两个简单的框架,并没有内部实现</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
------------------------------------
@Time : 2019/6/26 14:09
@Auth : linux超
@File : ClassFunc.py
@IDE: PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : 28174043@qq.com
@GROUP: 878565760
------------------------------------
</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
<span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> unittest
<span style="color: rgba(102, 217, 239, 1); font-style: italic">from unittest <span style="color: rgba(102, 217, 239, 1); font-style: italic">import mock</span></span><br>

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SubClass(object):
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> add(self, a, b):
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">两个数相加</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
      <span style="color: rgba(0, 0, 255, 1)">pass</span>

<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> TestSub(unittest.TestCase):<br>  """测试两个数相加用例"""
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_sub(self):
      sub </span>= SubClass()<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 初始化被测函数类实例</span>
      sub.add = mock.Mock(return_value=10)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> mock add方法 返回10</span>
      result = sub.add(5, 5)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 调用被测函数</span>
      self.assertEqual(result, 10)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 断言实际结果和预期结果</span>


<span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
    unittest.main()</span></pre>
</div>
<p>测试结果</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">.
</span>----------------------------------------------------------------------<span style="color: rgba(0, 0, 0, 1)">
Ran </span>1 test <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> 0.000s

OK

Process finished with exit code </span></pre>
</div>
<p>测试结果显示,测试用例执行已经通过</p>
<p>实际上mock模拟add方法的原理是 使用相同的对象方法接收mock的对象(使用sub.add接收),那么当mock对象被调用时(sub.add())就会返回return_value参数对应的数据</p>
<p>这样一来,表面看起来就是模拟了add方法(这里只是我个人理解,不对请忽略)</p>
<p>你可以做一个实验,把用例中的add改成别的名字也一样可以测试通过</p>
<p>ok,继续</p>
<p>我们用例编写完了,而且开发既然也把功能开发完了(要骂街吗?),既然真实的功能已经可以测试了,那么我们怎么在上面用例的基础上直接测试真实功能呢?</p>
<h4>完整的功能如何测试?</h4>
<p>我们把用例的代码稍做修改</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
------------------------------------
@Time : 2019/6/26 14:09
@Auth : linux超
@File : ClassFunc.py
@IDE: PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : 28174043@qq.com
@GROUP: 878565760
------------------------------------
</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
<span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> unittest
</span><span style="color: rgba(0, 0, 255, 1)">from</span> unittest <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> mock


</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SubClass(object):
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> add(self, a, b):
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">两个数相加</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
      <span style="color: rgba(0, 0, 255, 1)">return</span> a +<span style="color: rgba(0, 0, 0, 1)"> b

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> TestSub(unittest.TestCase):
    </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">测试两个数相加</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
    <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_sub(self):
      sub </span>= SubClass()<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 初始化被测函数类实例</span>
      sub.add = mock.Mock(return_value=10, side_effect=sub.add)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 传递side_effect关键字参数, 会覆盖return_value参数值, 使用真实的add方法测试</span>
      result = sub.add(5, 11)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 真正的调用被测函数</span>
      self.assertEqual(result, 16)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 断言实际结果和预期结果</span>


<span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
    unittest.main()</span></pre>
</div>
<h4>side_effect参数</h4>
<p>代码中我们给Mock方法添加了另一个关键字参数side_effect = sub.add, 这个参数和return_value 正好相反,当传递这个参数的时候return_value 参数就会失效</p>
<p>而side_effect生效,这里我给的参数值是sub.add 相当于add方法的地址,那么当调用add方法时就会真实的使用add方法,也就达到了我们测试实际的add 方法。</p>
<p>你也可以理解为当传递了side_effect参数且值为被测方法地址时,mock就不会起作用</p>
<p>side_effect接收的是一个可迭代序列,当传递多个值时,那么每次调用mock时会返回不同的值</p>
<div class="cnblogs_code">
<pre>mock_obj = mock.Mock(side_effect= )
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(mock_obj())
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(mock_obj())
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(mock_obj())
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(mock_obj())

输出
Traceback (most recent call last):
</span>1<span style="color: rgba(0, 0, 0, 1)">
File </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">D:/MyThreading/mymock.py</span><span style="color: rgba(128, 0, 0, 1)">"</span>, line 37, <span style="color: rgba(0, 0, 255, 1)">in</span> &lt;module&gt;
2
    <span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(mock_obj())
</span>3<span style="color: rgba(0, 0, 0, 1)">
File </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">C:\Python36\lib\unittest\mock.py</span><span style="color: rgba(128, 0, 0, 1)">"</span>, line 939, <span style="color: rgba(0, 0, 255, 1)">in</span> <span style="color: rgba(128, 0, 128, 1)">__call__</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span> _mock_self._mock_call(*args, **<span style="color: rgba(0, 0, 0, 1)">kwargs)
File </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">C:\Python36\lib\unittest\mock.py</span><span style="color: rgba(128, 0, 0, 1)">"</span>, line 998, <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> _mock_call
    result </span>=<span style="color: rgba(0, 0, 0, 1)"> next(effect)
StopIteration

Process finished with exit code </span>1</pre>
</div>
<p>当所有值被取完后就会报错(这个地方有点类似生成器的原理)</p>
<h4>存在依赖关系的功能如何测试?</h4>
<p>假设有这样一个场景:我们要测试一个支付接口但是这个支付接口又依赖一个第三方支付接口,那么第三方支付接口我们暂时没有权限使用,那么我们该如何测试我们自己这个接口呢?</p>
<p>看下面的实例</p>
<p>假设第三方接口和我们自己的支付接口如下</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
------------------------------------
@Time : 2019/6/26 15:09
@Auth : linux超
@File : PayMent.py
@IDE: PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : 28174043@qq.com
@GROUP: 878565760
------------------------------------
</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
<span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> requests


</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> PayApi(object):

    @staticmethod
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> auth(card, amount):
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
      第三方支付接口
      :param card: 卡号
      :param amount: 支付金额
      :return:
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
      pay_url </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://www.zhifubao.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 第三方支付接口地址</span>
      data = {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">card</span><span style="color: rgba(128, 0, 0, 1)">"</span>: card, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">amount</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: amount}
      response </span>= requests.post(pay_url, data=data)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 请求第三方支付接口</span>
      <span style="color: rgba(0, 0, 255, 1)">return</span> response<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 返回状态码</span>

    <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> pay(self, user_id, card, amount):
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
      我们自己的支付接口
      :param user_id: 用户id
      :param card: 卡号
      :param amount: 支付金额
      :return:
      </span><span style="color: rgba(128, 0, 0, 1)">"""<br>     # 调用第三方支付接口</span><span style="color: rgba(0, 0, 0, 1)">
      response </span>=<span style="color: rgba(0, 0, 0, 1)"> self.auth(card, amount)
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">:
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> response[<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">status_code</span><span style="color: rgba(128, 0, 0, 1)">'</span>] == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">200</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">用户{}支付金额{}成功</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">.format(user_id, amount))
                </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">支付成功</span><span style="color: rgba(128, 0, 0, 1)">'</span>
            <span style="color: rgba(0, 0, 255, 1)">elif</span> response[<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">status_code</span><span style="color: rgba(128, 0, 0, 1)">'</span>] == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">500</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">用户{}支付失败, 金额不变</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">.format(user_id))
                </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">支付失败</span><span style="color: rgba(128, 0, 0, 1)">'</span>
            <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">:
                </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">未知错误</span><span style="color: rgba(128, 0, 0, 1)">'</span>
      <span style="color: rgba(0, 0, 255, 1)">except</span><span style="color: rgba(0, 0, 0, 1)"> Exception:
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Error, 服务器异常!</span><span style="color: rgba(128, 0, 0, 1)">"</span>


<span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
    </span><span style="color: rgba(0, 0, 255, 1)">pass</span></pre>
</div>
<p>很明显第三方支付接口是无法访问的,因为接口的地址是我DIY的,为了模拟实际中我们无法使用的第三方支付接口</p>
<p>编写测试用例</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
------------------------------------
@Time : 2019/6/26 15:22
@Auth : linux超
@File : testpay.py
@IDE: PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : 28174043@qq.com
@GROUP: 878565760
------------------------------------
</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
<span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> unittest
</span><span style="color: rgba(0, 0, 255, 1)">from</span> unittest <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> mock

</span><span style="color: rgba(0, 0, 255, 1)">from</span> payment.PayMent <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> PayApi


</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> TestPayApi(unittest.TestCase):

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_success(self):
      pay </span>=<span style="color: rgba(0, 0, 0, 1)"> PayApi()
      pay.auth </span>= mock.Mock(return_value={<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">status_code</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">200</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">})
      status </span>= pay.pay(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1000</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">10000</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      self.assertEqual(status, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">支付成功</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_fail(self):
      pay </span>=<span style="color: rgba(0, 0, 0, 1)"> PayApi()
      pay.auth </span>= mock.Mock(return_value={<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">status_code</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">500</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">})
      status </span>= pay.pay(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1000</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">10000</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      self.assertEqual(status, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">支付失败</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_error(self):
      pay </span>=<span style="color: rgba(0, 0, 0, 1)"> PayApi()
      pay.auth </span>= mock.Mock(return_value={<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">status_code</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">300</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">})
      status </span>= pay.pay(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1000</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">10000</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      self.assertEqual(status, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">未知错误</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_exception(self):
      pay </span>=<span style="color: rgba(0, 0, 0, 1)"> PayApi()
      pay.auth </span>= mock.Mock(return_value=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">200</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      status </span>= pay.pay(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1000</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">10000</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      self.assertEqual(status, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Error, 服务器异常!</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)


</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
    unittest.main()</span></pre>
</div>
<p>测试输出结果</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">....用户1000支付失败, 金额不变
用户1000支付金额10000成功

</span>----------------------------------------------------------------------<span style="color: rgba(0, 0, 0, 1)">
Ran </span>4 tests <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> 0.001s

OK

Process finished with exit code 0</span></pre>
</div>
<p>从执行结果可以看出,即使第三方支付接口无法使用,但是我们自己的支付接口仍然测试通过了</p>
<p>也许有人会问,第三方支付都不能用,我们的测试结果是否是有效的呢?</p>
<p>通常我们在测试一个模块的时候,我们是可以认为其他模块的功能是正常的,只针对目标模块进行测试是没有任何问题的,所以说测试结果也是正确的</p>
<p>其实上述代码还可以使用另一种方式来写</p>
<h4>mock对象的方法</h4>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
------------------------------------
@Time : 2019/6/26 15:22
@Auth : linux超
@File : testpay.py
@IDE: PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : 28174043@qq.com
@GROUP: 878565760
------------------------------------
</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
<span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> unittest
</span><span style="color: rgba(0, 0, 255, 1)">from</span> unittest <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> mock
</span><span style="color: rgba(0, 0, 255, 1)">from</span> unittest.mock <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> patch

</span><span style="color: rgba(0, 0, 255, 1)">from</span> payment.PayMent <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> PayApi


</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> TestPayApi(unittest.TestCase):

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> setUp(self):
      self.pay </span>=<span style="color: rgba(0, 0, 0, 1)"> PayApi()

    @patch.object(PayApi, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">auth</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_success(self, mock_auth):

      mock_auth.return_value </span>= {<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">status_code</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">200</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">}
      status </span>= self.pay.pay(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1000</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">10000</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      self.assertEqual(status, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">支付成功</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

    @patch.object(PayApi, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">auth</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_fail(self, mock_auth):
      mock_auth.return_value</span>={<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">status_code</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">500</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">}
      status </span>= self.pay.pay(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1000</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">10000</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      self.assertEqual(status, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">支付失败</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

    @patch.object(PayApi, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">auth</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_error(self, mock_auth):
      mock_auth.return_value</span>={<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">status_code</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">300</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">}
      status </span>= self.pay.pay(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1000</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">10000</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      self.assertEqual(status, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">未知错误</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

    @patch.object(PayApi, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">auth</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_exception(self, mock_auth):
      mock_auth.return_value</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">200</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
      status </span>= self.pay.pay(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1000</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">10000</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      self.assertEqual(status, </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Error, 服务器异常!</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)


</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
    unittest.main()</span></pre>
</div>
<p>还有mock一个普通函数,mock多个方法等,这里先不赘述,写法和上面实例差不多</p>
<h3>最后</h3>
<p>mock还有很多自带的功能方法</p>
<p>且mock功能很强大,也不是一句两句话就能说完了,本篇文章主要介绍了mock的基本使用方法,甚是简单,对于实际中如何应用,如何掌握更强大的方法还需自己慢慢摸索</p>

</div>
<div id="MySignature" role="contentinfo">
    <p>----------------------------真正的勇士, 敢于直面惨淡的Warning、 敢于正视淋漓的Error--------------------------</p>
    <p>
      <span style="color: red">版权声明</span>
    </p>
    <p></p>
    <hr style="color: red">
    <p>
      <span style="color: red">出处:</span>
      
            博客园Linux超的技术博客--https://www.cnblogs.com/linuxchao/
      
    </p>
    <p>
      <span style="color: red">您的支持是对博主最大的鼓励,感谢您的认真阅读</span>
    </p>
    <p>
      <span style="color: red">
            本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,
            且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
      </span>
    </p>
    <p>
      <span style="color: red">作者:</span>
      <span style="color: black">Linux超</span>
    </p><br><br>
来源:https://www.cnblogs.com/linuxchao/p/linuxchao-mock.html
頁: [1]
查看完整版本: python接口自动化之mock模块基本使用