周师兄 發表於 2020-1-25 22:19:00

python接口自动化测试 - mock模块基本使用介绍

<h2>mock简介</h2>
<ul>
<li>py3已将mock集成到unittest库中</li>
<li>为的就是更好的进行单元测试</li>
<li>简单理解,<strong>模拟接口返回参数</strong></li>
<li>通俗易懂,<strong>直接修改接口返回参数的值</strong></li>
<li>官方文档:https://docs.python.org/zh-cn/3/library/unittest.mock.html</li>
</ul>
<p>&nbsp;</p>
<h2><strong>mock作用</strong></h2>
<h3>解决依赖问题,达到解耦作用</h3>
<p>当我们测试某个<strong>目标接口(模块)</strong>时,该接口<strong>依赖其他接口</strong>,当被依赖的接口未开发完成时,可以<strong>用mock模拟被依赖接口</strong>,完成目标接口的测试</p>
<p>&nbsp;</p>
<h3>模拟复杂业务的接口</h3>
<p>当我们测试某个<strong>目标接口(模块)</strong>,该接口<strong>依赖一个非常复杂的接口</strong>时,可以<strong>用mock来模拟这个复杂的业务接口</strong>;也解决接口依赖一样的原理</p>
<p>&nbsp;</p>
<h3>单元测试</h3>
<p>如果某个接口(模块)未开发完成时,又需要编写测试用例,则可以通过mock模拟该接口(模块)进行测试</p>
<p>&nbsp;</p>
<h3>前后端联调</h3>
<p>前端开发的页面需要根据后端返回的不同状态码展示不同的页面,当后端接口未开发完成时,也可通过mock来模拟后端接口返回自己想要的数据</p>
<p>&nbsp;</p>
<h2>mock类解读</h2>
<p><span class="cnblogs_code"><span style="color: rgba(0, 0, 255, 1)">class</span> Mock(spec=None,side_effect=None,return_value=DEFFAULT,name=None)</span>&nbsp;</p>
<ul>
<li><strong>secp</strong>:定义mock对象的属性值,可以是列表,字符串,甚至一个对象或者实例&nbsp;</li>
<li><strong>side_effect</strong>:可以用来<strong>抛出异常</strong>或者动态改变返回值,它必须是一个iterator(列表),它会覆盖return_value</li>
<li><strong>return_value</strong>:定义mock方法的返回值,它可以是一个值,可以是一个对象(如果存在side_effect参数那这个就没有用,也就是不能同时用)</li>
<li><strong>name</strong>:作为mock对象的一个标识,在print时可以看到</li>
</ul>
<p>&nbsp;</p>
<h2>mock实际使用</h2>
<h3>一个未开发完成的功能如何测试?</h3>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</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(0, 128, 128, 1)"> 2</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, 128, 128, 1)"> 3</span>   <span style="color: rgba(0, 0, 255, 1)">pass</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span>
<span style="color: rgba(0, 128, 128, 1)"> 6</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(0, 128, 128, 1)"> 7</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, 128, 128, 1)"> 8</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_sub(self):
</span><span style="color: rgba(0, 128, 128, 1)">10</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 创建一个mock对象 return_value代表mock一个数据</span>
<span style="color: rgba(0, 128, 128, 1)">11</span>         mock_add = mock.Mock(return_value=15<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">12</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将mock对象赋予给被测函数</span>
<span style="color: rgba(0, 128, 128, 1)">13</span>         add =<span style="color: rgba(0, 0, 0, 1)"> mock_add
</span><span style="color: rgba(0, 128, 128, 1)">14</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 调用被测函数</span>
<span style="color: rgba(0, 128, 128, 1)">15</span>         result = add(5, 5<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">16</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 断言实际结果和预期结果</span>
<span style="color: rgba(0, 128, 128, 1)">17</span>         self.assertEqual(result, 15)</pre>
</div>
<p>&nbsp;</p>
<h3>一个完成开发的功能如何测试?</h3>
<div class="cnblogs_code">
<pre><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_add2(self):
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 初始化被测函数类实例</span>
      sub =<span style="color: rgba(0, 0, 0, 1)"> SubClass()
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 创建一个mock对象 return_value代表mock一个数据</span>
      <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 传递side_effect关键字参数, 会覆盖return_value参数值, 使用真实的add方法测试</span>
      sub.add = Mock(return_value=15, side_effect=<span style="color: rgba(0, 0, 0, 1)">sub.add)
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 调用被测函数</span>
      result = sub.add(5, 5<span style="color: rgba(0, 0, 0, 1)">)
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 断言实际结果和预期结果</span>
      self.assertEqual(result, 10)</pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>side_effect:</strong>这里给的参数值是sub.add相当于add方法的地址,当我们调用add方法时就会调用真实的add方法</p>
<p><strong>简单理解成:</strong>传递了side_effect参数且值为被测函数地址时,mock不会起作用;<strong>两者不可共存</strong></p>
<p>另外,side_effect接受的是一个可迭代序列,当传递多个值时,每次调用mock时会返回不同的值;如下</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> mock_obj = mock.Mock(side_effect= )
</span><span style="color: rgba(0, 128, 128, 1)"> 2</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, 128, 128, 1)"> 3</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, 128, 128, 1)"> 4</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, 128, 128, 1)"> 5</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, 128, 128, 1)"> 6</span>
<span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 输出</span>
<span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)">Traceback (most recent call last):
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> 1
<span style="color: rgba(0, 128, 128, 1)">10</span>   File <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;
<span style="color: rgba(0, 128, 128, 1)">11</span> 2
<span style="color: rgba(0, 128, 128, 1)">12</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, 128, 128, 1)">13</span> 3
<span style="color: rgba(0, 128, 128, 1)">14</span>   File <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, 128, 128, 1)">15</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)
</span><span style="color: rgba(0, 128, 128, 1)">16</span>   File <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
</span><span style="color: rgba(0, 128, 128, 1)">17</span>   result =<span style="color: rgba(0, 0, 0, 1)"> next(effect)
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 0, 1)">StopIteration</span></pre>
</div>
<p>&nbsp;</p>
<h4 id="autoid-0-4-3">存在依赖关系的功能如何测试?</h4>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 支付类</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Payment:
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> requestOutofSystem(self, card_num, amount):
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span>         <span style="color: rgba(128, 0, 0, 1)">'''</span>
<span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(128, 0, 0, 1)">      请求第三方外部支付接口,并返回响应码
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(128, 0, 0, 1)">      :param card_num: 卡号
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(128, 0, 0, 1)">      :param amount: 支付金额
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(128, 0, 0, 1)">      :return: 返回状态码,200 代表支付成功,500 代表支付异常失败
</span><span style="color: rgba(0, 128, 128, 1)">10</span>         <span style="color: rgba(128, 0, 0, 1)">'''</span>
<span style="color: rgba(0, 128, 128, 1)">11</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 第三方支付接口请求地址(故意写错)</span>
<span style="color: rgba(0, 128, 128, 1)">12</span>         url = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://third.payment.pay/</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">13</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 请求参数</span>
<span style="color: rgba(0, 128, 128, 1)">14</span>         data = {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">card_num</span><span style="color: rgba(128, 0, 0, 1)">"</span>: card_num, <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}
</span><span style="color: rgba(0, 128, 128, 1)">15</span>         response = requests.post(url, data=<span style="color: rgba(0, 0, 0, 1)">data)
</span><span style="color: rgba(0, 128, 128, 1)">16</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 返回状态码</span>
<span style="color: rgba(0, 128, 128, 1)">17</span>         <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> response.status_code
</span><span style="color: rgba(0, 128, 128, 1)">18</span>
<span style="color: rgba(0, 128, 128, 1)">19</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> doPay(self, user_id, card_num, amount):
</span><span style="color: rgba(0, 128, 128, 1)">20</span>         <span style="color: rgba(128, 0, 0, 1)">'''</span>
<span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(128, 0, 0, 1)">      支付
</span><span style="color: rgba(0, 128, 128, 1)">22</span> <span style="color: rgba(128, 0, 0, 1)">      :param userId: 用户ID
</span><span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(128, 0, 0, 1)">      :param card_num: 卡号
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(128, 0, 0, 1)">      :param amount: 支付金额
</span><span style="color: rgba(0, 128, 128, 1)">25</span> <span style="color: rgba(128, 0, 0, 1)">      :return:
</span><span style="color: rgba(0, 128, 128, 1)">26</span>         <span style="color: rgba(128, 0, 0, 1)">'''</span>
<span style="color: rgba(0, 128, 128, 1)">27</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, 128, 128, 1)">28</span>             <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 调用第三方支付接口请求进行真实扣款</span>
<span style="color: rgba(0, 128, 128, 1)">29</span>             resp =<span style="color: rgba(0, 0, 0, 1)"> self.requestOutofSystem(card_num, amount)
</span><span style="color: rgba(0, 128, 128, 1)">30</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)">, resp)
</span><span style="color: rgba(0, 128, 128, 1)">31</span>         <span style="color: rgba(0, 0, 255, 1)">except</span><span style="color: rgba(0, 0, 0, 1)"> TimeoutError:
</span><span style="color: rgba(0, 128, 128, 1)">32</span>             <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 如果超时就重新调用一次</span>
<span style="color: rgba(0, 128, 128, 1)">33</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)">)
</span><span style="color: rgba(0, 128, 128, 1)">34</span>             resp =<span style="color: rgba(0, 0, 0, 1)"> self.requestOutofSystem(card_num, amount)
</span><span style="color: rgba(0, 128, 128, 1)">35</span>
<span style="color: rgba(0, 128, 128, 1)">36</span>         <span style="color: rgba(0, 0, 255, 1)">if</span> resp == 200<span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 128, 128, 1)">37</span>             <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 返回第三方支付成功,则进行系统里面的扣款并记录支付记录等操作</span>
<span style="color: rgba(0, 128, 128, 1)">38</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)">{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, 128, 128, 1)">39</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)">success</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 128, 128, 1)">40</span>
<span style="color: rgba(0, 128, 128, 1)">41</span>         <span style="color: rgba(0, 0, 255, 1)">elif</span> resp == 500<span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 128, 128, 1)">42</span>             <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 返回第三方支付失败,则不进行扣款</span>
<span style="color: rgba(0, 128, 128, 1)">43</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)">{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, 128, 128, 1)">44</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)">fail</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 128, 128, 1)">45</span>
<span style="color: rgba(0, 128, 128, 1)">46</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 单元测试类</span>
<span style="color: rgba(0, 128, 128, 1)">47</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> payTest(unittest.TestCase):
</span><span style="color: rgba(0, 128, 128, 1)">48</span>
<span style="color: rgba(0, 128, 128, 1)">49</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_pay_success(self):
</span><span style="color: rgba(0, 128, 128, 1)">50</span>         pay =<span style="color: rgba(0, 0, 0, 1)"> Payment()
</span><span style="color: rgba(0, 128, 128, 1)">51</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 模拟第三方支付接口返回200</span>
<span style="color: rgba(0, 128, 128, 1)">52</span>         pay.requestOutofSystem = mock.Mock(return_value=200<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">53</span>         resp = pay.doPay(user_id=1, card_num=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345678</span><span style="color: rgba(128, 0, 0, 1)">'</span>, amount=100<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">54</span>         self.assertEqual(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">success</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, resp)
</span><span style="color: rgba(0, 128, 128, 1)">55</span>
<span style="color: rgba(0, 128, 128, 1)">56</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_pay_fail(self):
</span><span style="color: rgba(0, 128, 128, 1)">57</span>         pay =<span style="color: rgba(0, 0, 0, 1)"> Payment()
</span><span style="color: rgba(0, 128, 128, 1)">58</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 模拟第三方支付接口返回500</span>
<span style="color: rgba(0, 128, 128, 1)">59</span>         pay.requestOutofSystem = mock.Mock(return_value=500<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">60</span>         resp = pay.doPay(user_id=1, card_num=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345678</span><span style="color: rgba(128, 0, 0, 1)">'</span>, amount=100<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">61</span>         self.assertEqual(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">fail</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, resp)
</span><span style="color: rgba(0, 128, 128, 1)">62</span>
<span style="color: rgba(0, 128, 128, 1)">63</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_pay_time_success(self):
</span><span style="color: rgba(0, 128, 128, 1)">64</span>         pay =<span style="color: rgba(0, 0, 0, 1)"> Payment()
</span><span style="color: rgba(0, 128, 128, 1)">65</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 模拟第三方支付接口首次支付超时,重试第二次成功</span>
<span style="color: rgba(0, 128, 128, 1)">66</span>         pay.requestOutofSystem = mock.Mock(side_effect=)
</span><span style="color: rgba(0, 128, 128, 1)">67</span>         resp = pay.doPay(user_id=1, card_num=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345678</span><span style="color: rgba(128, 0, 0, 1)">'</span>, amount=100<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">68</span>         self.assertEqual(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">success</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, resp)
</span><span style="color: rgba(0, 128, 128, 1)">69</span>
<span style="color: rgba(0, 128, 128, 1)">70</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_pay_time_fail(self):
</span><span style="color: rgba(0, 128, 128, 1)">71</span>         pay =<span style="color: rgba(0, 0, 0, 1)"> Payment()
</span><span style="color: rgba(0, 128, 128, 1)">72</span>         <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 模拟第三方支付接口首次支付超时,重试第二次失败</span>
<span style="color: rgba(0, 128, 128, 1)">73</span>         pay.requestOutofSystem = mock.Mock(side_effect=)
</span><span style="color: rgba(0, 128, 128, 1)">74</span>         resp = pay.doPay(user_id=1, card_num=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">12345678</span><span style="color: rgba(128, 0, 0, 1)">'</span>, amount=100<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">75</span>         self.assertEqual(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">fail</span><span style="color: rgba(128, 0, 0, 1)">'</span>, resp)</pre>
</div>
<p>也许有小伙伴会问,第三方支付都不能用,我们的测试结果是否是有效的呢?</p>
<p>通常在测试一个模块的时候,是可以认为<strong>其他模块的功能是正常的,只针对目标模块进行测试是没有任何问题的</strong>,所以说测试结果也是正确的</p>
<p>&nbsp;</p>
<h2>mock装饰器</h2>
<p>一共两种格式</p>
<ol>
<li>&nbsp;<span class="cnblogs_code">@patch(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">module名字.方法名</span><span style="color: rgba(128, 0, 0, 1)">'</span>)</span>&nbsp;</li>
<li>&nbsp;<span class="cnblogs_code">@patch.object(类名, <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>&nbsp;</li>
</ol>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 装饰类演示</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 255, 1)">from</span> mock <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> Mock, patch
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 单独的相乘函数</span>
<span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> multiple(a, b):
</span><span style="color: rgba(0, 128, 128, 1)"> 7</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, 128, 128, 1)"> 8</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span>
<span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 单独的捕获Exception函数</span>
<span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> is_error():
</span><span style="color: rgba(0, 128, 128, 1)">12</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, 128, 128, 1)">13</span>         os.mkdir(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">11</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">14</span>         <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> False
</span><span style="color: rgba(0, 128, 128, 1)">15</span>   <span style="color: rgba(0, 0, 255, 1)">except</span><span style="color: rgba(0, 0, 0, 1)"> Exception as e:
</span><span style="color: rgba(0, 128, 128, 1)">16</span>         <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> True
</span><span style="color: rgba(0, 128, 128, 1)">17</span>
<span style="color: rgba(0, 128, 128, 1)">18</span>
<span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 计算类,包含add方法</span>
<span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> calculator(object):
</span><span style="color: rgba(0, 128, 128, 1)">21</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(0, 128, 128, 1)">22</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, 128, 128, 1)">23</span>
<span style="color: rgba(0, 128, 128, 1)">24</span>
<span style="color: rgba(0, 128, 128, 1)">25</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 装饰类演示 - 单元测试类</span>
<span style="color: rgba(0, 128, 128, 1)">26</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> TestProducer(unittest.TestCase):
</span><span style="color: rgba(0, 128, 128, 1)">27</span>
<span style="color: rgba(0, 128, 128, 1)">28</span>   <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> case执行前</span>
<span style="color: rgba(0, 128, 128, 1)">29</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> setUp(self):
</span><span style="color: rgba(0, 128, 128, 1)">30</span>         self.calculator =<span style="color: rgba(0, 0, 0, 1)"> calculator()
</span><span style="color: rgba(0, 128, 128, 1)">31</span>
<span style="color: rgba(0, 128, 128, 1)">32</span>   <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> mock一个函数,注意也要指定module</span>
<span style="color: rgba(0, 128, 128, 1)">33</span>   @patch(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">mock_learn.multiple</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">34</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_multiple(self, mock_multiple):
</span><span style="color: rgba(0, 128, 128, 1)">35</span>         mock_multiple.return_value = 3
<span style="color: rgba(0, 128, 128, 1)">36</span>         self.assertEqual(multiple(8, 14), 3<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">37</span>
<span style="color: rgba(0, 128, 128, 1)">38</span>   <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> mock一个类对象的方法</span>
<span style="color: rgba(0, 128, 128, 1)">39</span>   @patch.object(calculator, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">add</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">40</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_add(self, mock_add):
</span><span style="color: rgba(0, 128, 128, 1)">41</span>         mock_add.return_value = 3
<span style="color: rgba(0, 128, 128, 1)">42</span>         self.assertEqual(self.calculator.add(8, 14), 3<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">43</span>
<span style="color: rgba(0, 128, 128, 1)">44</span>   <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> mock调用方法返回多个不同的值</span>
<span style="color: rgba(0, 128, 128, 1)">45</span>   @patch.object(calculator, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">add</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">46</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_effect(self, mock_add):
</span><span style="color: rgba(0, 128, 128, 1)">47</span>         mock_add.side_effect =
</span><span style="color: rgba(0, 128, 128, 1)">48</span>         self.assertEqual(self.calculator.add(8, 14), 1<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">49</span>         self.assertEqual(self.calculator.add(8, 14), 2<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">50</span>         self.assertEqual(self.calculator.add(8, 14), 3<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">51</span>
<span style="color: rgba(0, 128, 128, 1)">52</span>   <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> mock的函数抛出Exception</span>
<span style="color: rgba(0, 128, 128, 1)">53</span>   @patch(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">os.mkdir</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">54</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_exception(self, mkdir):
</span><span style="color: rgba(0, 128, 128, 1)">55</span>         mkdir.side_effect =<span style="color: rgba(0, 0, 0, 1)"> Exception
</span><span style="color: rgba(0, 128, 128, 1)">56</span> <span style="color: rgba(0, 0, 0, 1)">      self.assertEqual(is_error(), True)
</span><span style="color: rgba(0, 128, 128, 1)">57</span>
<span style="color: rgba(0, 128, 128, 1)">58</span>   <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> mock多个函数,注意函数调用顺序</span>
<span style="color: rgba(0, 128, 128, 1)">59</span>   @patch.object(calculator, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">add</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">60</span>   @patch(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">mock_learn.multiple</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">61</span>   <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_more(self, mock_multiple, mock_add):
</span><span style="color: rgba(0, 128, 128, 1)">62</span>         mock_add.return_value = 1
<span style="color: rgba(0, 128, 128, 1)">63</span>         mock_multiple.return_value = 4
<span style="color: rgba(0, 128, 128, 1)">64</span>         self.assertEqual(self.calculator.add(3, 3), 1<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">65</span>         self.assertEqual(multiple(3, 3), 4)</pre>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/poloyy/p/12233507.html
頁: [1]
查看完整版本: python接口自动化测试 - mock模块基本使用介绍