2463 lines
348 KiB
HTML
2463 lines
348 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
|
||
<head>
|
||
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
|
||
<title>unittest.mock --- 模拟对象库 — Python 3.8.20 文档</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
|
||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
<script src="../_static/language_data.js"></script>
|
||
<script src="../_static/translations.js"></script>
|
||
|
||
<script src="../_static/sidebar.js"></script>
|
||
|
||
<link rel="search" type="application/opensearchdescription+xml"
|
||
title="在 Python 3.8.20 文档 中搜索"
|
||
href="../_static/opensearch.xml"/>
|
||
<link rel="author" title="关于这些文档" href="../about.html" />
|
||
<link rel="index" title="索引" href="../genindex.html" />
|
||
<link rel="search" title="搜索" href="../search.html" />
|
||
<link rel="copyright" title="版权所有" href="../copyright.html" />
|
||
<link rel="next" title="unittest.mock --- 上手指南" href="unittest.mock-examples.html" />
|
||
<link rel="prev" title="unittest --- 单元测试框架" href="unittest.html" />
|
||
<link rel="canonical" href="https://docs.python.org/3/library/unittest.mock.html" />
|
||
|
||
|
||
|
||
|
||
|
||
<style>
|
||
@media only screen {
|
||
table.full-width-table {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
|
||
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
||
<script type="text/javascript" src="../_static/menu.js"></script>
|
||
|
||
</head>
|
||
<body>
|
||
<div class="mobile-nav">
|
||
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
|
||
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
|
||
<label for="menuToggler" class="toggler__label">
|
||
<span></span>
|
||
</label>
|
||
<nav class="nav-content" role="navigation">
|
||
<a href="https://www.python.org/" class="nav-logo">
|
||
<img src="../_static/py.svg" alt="Logo"/>
|
||
</a>
|
||
<div class="version_switcher_placeholder"></div>
|
||
<form role="search" class="search" action="../search.html" method="get">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
|
||
<path fill-rule="nonzero"
|
||
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
|
||
</svg>
|
||
<input type="text" name="q" aria-label="快速搜索"/>
|
||
<input type="submit" value="转向"/>
|
||
</form>
|
||
</nav>
|
||
<div class="menu-wrapper">
|
||
<nav class="menu" role="navigation" aria-label="main navigation">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<h3><a href="../contents.html">目录</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest.mock</span></code> --- 模拟对象库</a><ul>
|
||
<li><a class="reference internal" href="#quick-guide">快速上手</a></li>
|
||
<li><a class="reference internal" href="#the-mock-class">Mock 类</a><ul>
|
||
<li><a class="reference internal" href="#calling">调用</a></li>
|
||
<li><a class="reference internal" href="#deleting-attributes">删除属性</a></li>
|
||
<li><a class="reference internal" href="#mock-names-and-the-name-attribute">Mock 的名称与 name 属性</a></li>
|
||
<li><a class="reference internal" href="#attaching-mocks-as-attributes">附加 Mock 作为属性</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#the-patchers">patch 装饰器</a><ul>
|
||
<li><a class="reference internal" href="#patch">patch</a></li>
|
||
<li><a class="reference internal" href="#patch-object">patch.object</a></li>
|
||
<li><a class="reference internal" href="#patch-dict">patch.dict</a></li>
|
||
<li><a class="reference internal" href="#patch-multiple">patch.multiple</a></li>
|
||
<li><a class="reference internal" href="#patch-methods-start-and-stop">补丁方法: start 和 stop</a></li>
|
||
<li><a class="reference internal" href="#patch-builtins">为内置对象打补丁</a></li>
|
||
<li><a class="reference internal" href="#test-prefix">TEST_PREFIX</a></li>
|
||
<li><a class="reference internal" href="#nesting-patch-decorators">嵌套补丁装饰器</a></li>
|
||
<li><a class="reference internal" href="#where-to-patch">补丁的目标</a></li>
|
||
<li><a class="reference internal" href="#patching-descriptors-and-proxy-objects">对描述器和代理对象打补丁</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#magicmock-and-magic-method-support">MagicMock 与魔术方法支持</a><ul>
|
||
<li><a class="reference internal" href="#mocking-magic-methods">模拟魔术方法</a></li>
|
||
<li><a class="reference internal" href="#magic-mock">MagicMock</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#helpers">辅助对象</a><ul>
|
||
<li><a class="reference internal" href="#sentinel">sentinel</a></li>
|
||
<li><a class="reference internal" href="#default">DEFAULT</a></li>
|
||
<li><a class="reference internal" href="#call">call</a></li>
|
||
<li><a class="reference internal" href="#create-autospec">create_autospec</a></li>
|
||
<li><a class="reference internal" href="#any">ANY</a></li>
|
||
<li><a class="reference internal" href="#filter-dir">FILTER_DIR</a></li>
|
||
<li><a class="reference internal" href="#mock-open">mock_open</a></li>
|
||
<li><a class="reference internal" href="#autospeccing">自动 spec</a></li>
|
||
<li><a class="reference internal" href="#sealing-mocks">将 mock 封包</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="unittest.html"
|
||
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest</span></code> --- 单元测试框架</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="unittest.mock-examples.html"
|
||
title="下一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest.mock</span></code> --- 上手指南</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<h3>本页</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">报告 Bug</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.8/Doc/library/unittest.mock.rst"
|
||
rel="nofollow">显示源代码
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
|
||
这个文档所针对的是一个已不再受支持的 Python 旧版本。
|
||
你应当升级版本,并阅读
|
||
<a href="/3/library/unittest.mock.html"> Python 当前稳定版本的文档</a>.
|
||
</div>
|
||
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>导航</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="总目录"
|
||
accesskey="I">索引</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python 模块索引"
|
||
>模块</a> |</li>
|
||
<li class="right" >
|
||
<a href="unittest.mock-examples.html" title="unittest.mock --- 上手指南"
|
||
accesskey="N">下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="unittest.html" title="unittest --- 单元测试框架"
|
||
accesskey="P">上一页</a> |</li>
|
||
|
||
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.8.20 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="development.html" accesskey="U">开发工具</a> »</li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
|
||
<input type="submit" value="转向" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section id="module-unittest.mock">
|
||
<span id="unittest-mock-mock-object-library"></span><h1><a class="reference internal" href="#module-unittest.mock" title="unittest.mock: Mock object library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest.mock</span></code></a> --- 模拟对象库<a class="headerlink" href="#module-unittest.mock" title="永久链接至标题">¶</a></h1>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能.</span></p>
|
||
</div>
|
||
<p><strong>源代码:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/3.8/Lib/unittest/mock.py">Lib/unittest/mock.py</a></p>
|
||
<hr class="docutils" />
|
||
<p><a class="reference internal" href="#module-unittest.mock" title="unittest.mock: Mock object library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest.mock</span></code></a> 是一个用于测试的Python库。它允许使用模拟对象来替换受测系统的一些部分,并对这些部分如何被使用进行断言判断。</p>
|
||
<p><a class="reference internal" href="#module-unittest.mock" title="unittest.mock: Mock object library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest.mock</span></code></a> 提供了一个核心类 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 用于消除在整个测试套件中创建大量存根(stub)的需求。在执行一个操作后,你就可以用断言去判断:哪些方法/属性及其参数被调用到了。你还可以用常规的方式指定返回值并设置所需的属性。</p>
|
||
<p>此外,mock 还提供了用于修补测试范围内模块和类级别属性的 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 装饰器,和用于创建独特对象的 <a class="reference internal" href="#unittest.mock.sentinel" title="unittest.mock.sentinel"><code class="xref py py-const docutils literal notranslate"><span class="pre">sentinel</span></code></a> 。 阅读 <a class="reference internal" href="#quick-guide">quick guide</a> 中的案例了解如何使用 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> ,<a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 和 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 。</p>
|
||
<p>Mock 是为 <a class="reference internal" href="unittest.html#module-unittest" title="unittest: Unit testing framework for Python."><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest</span></code></a> 而设计,且简单易用。模拟基于 'action -> assertion' 模式,而不是许多模拟框架所使用的 'record -> replay'模式。</p>
|
||
<p>在 Python 的早期版本要单独使用 <a class="reference internal" href="#module-unittest.mock" title="unittest.mock: Mock object library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest.mock</span></code></a> ,在 <a class="reference external" href="https://pypi.org/project/mock">PyPI 获取 mock</a></p>
|
||
<section id="quick-guide">
|
||
<h2>快速上手<a class="headerlink" href="#quick-guide" title="永久链接至标题">¶</a></h2>
|
||
<p>当您访问对象时, <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 和 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 将创建所有属性和方法,并保存他们在使用时的细节。你可以通过配置,指定返回值或者限制可访问属性,然后断言他们如何被调用。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">unittest.mock</span> <span class="kn">import</span> <span class="n">MagicMock</span>
|
||
<span class="gp">>>> </span><span class="n">thing</span> <span class="o">=</span> <span class="n">ProductionClass</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">thing</span><span class="o">.</span><span class="n">method</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">thing</span><span class="o">.</span><span class="n">method</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s1">'value'</span><span class="p">)</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">thing</span><span class="o">.</span><span class="n">method</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s1">'value'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>通过 <code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code> 设置副作用(side effects) ,可以是一个 mock 被调用是抛出的异常</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">side_effect</span><span class="o">=</span><span class="ne">KeyError</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">KeyError</span>: <span class="n">'foo'</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">values</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'a'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">'b'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">:</span> <span class="mi">3</span><span class="p">}</span>
|
||
<span class="gp">>>> </span><span class="k">def</span> <span class="nf">side_effect</span><span class="p">(</span><span class="n">arg</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">values</span><span class="p">[</span><span class="n">arg</span><span class="p">]</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="n">side_effect</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="s1">'a'</span><span class="p">),</span> <span class="n">mock</span><span class="p">(</span><span class="s1">'b'</span><span class="p">),</span> <span class="n">mock</span><span class="p">(</span><span class="s1">'c'</span><span class="p">)</span>
|
||
<span class="go">(1, 2, 3)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(),</span> <span class="n">mock</span><span class="p">(),</span> <span class="n">mock</span><span class="p">()</span>
|
||
<span class="go">(5, 4, 3)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Mock 还可以通过其他方法配置和控制其行为。例如 mock 可以通过设置 <em>spec</em> 参数来从一个对象中获取其规格(specification)。如果访问 mock 的属性或方法不在 spec 中,会报 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a> 错误。</p>
|
||
<p>使用 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 装饰去/上下文管理器,可以更方便地测试一个模块下的类或对象。你指定的对象会在测试过程中替换成 mock (或者其他对象),测试结束后恢复。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">unittest.mock</span> <span class="kn">import</span> <span class="n">patch</span>
|
||
<span class="gp">>>> </span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'module.ClassName2'</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'module.ClassName1'</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">MockClass1</span><span class="p">,</span> <span class="n">MockClass2</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">module</span><span class="o">.</span><span class="n">ClassName1</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="n">module</span><span class="o">.</span><span class="n">ClassName2</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">MockClass1</span> <span class="ow">is</span> <span class="n">module</span><span class="o">.</span><span class="n">ClassName1</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">MockClass2</span> <span class="ow">is</span> <span class="n">module</span><span class="o">.</span><span class="n">ClassName2</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">MockClass1</span><span class="o">.</span><span class="n">called</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">MockClass2</span><span class="o">.</span><span class="n">called</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">test</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>当你嵌套 patch 装饰器时,mock 将以执行顺序传递给装饰器函数(<em>Python</em> 装饰器正常顺序)。由于从下至上,因此在上面的示例中,首先 mock 传入的 <code class="docutils literal notranslate"><span class="pre">module.ClassName1</span></code> 。</p>
|
||
<p>在查找对象的名称空间中修补对象使用 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 。使用起来很简单,阅读 <a class="reference internal" href="#where-to-patch"><span class="std std-ref">在哪里打补丁</span></a> 来快速上手。</p>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 也可以 with 语句中使用上下文管理。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="o">.</span><span class="n">object</span><span class="p">(</span><span class="n">ProductionClass</span><span class="p">,</span> <span class="s1">'method'</span><span class="p">,</span> <span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="k">as</span> <span class="n">mock_method</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="n">thing</span> <span class="o">=</span> <span class="n">ProductionClass</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="n">thing</span><span class="o">.</span><span class="n">method</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock_method</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>还有一个 <a class="reference internal" href="#unittest.mock.patch.dict" title="unittest.mock.patch.dict"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.dict()</span></code></a> 用于在一定范围内设置字典中的值,并在测试结束时将字典恢复为其原始状态:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">foo</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'key'</span><span class="p">:</span> <span class="s1">'value'</span><span class="p">}</span>
|
||
<span class="gp">>>> </span><span class="n">original</span> <span class="o">=</span> <span class="n">foo</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="o">.</span><span class="n">dict</span><span class="p">(</span><span class="n">foo</span><span class="p">,</span> <span class="p">{</span><span class="s1">'newkey'</span><span class="p">:</span> <span class="s1">'newvalue'</span><span class="p">},</span> <span class="n">clear</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">foo</span> <span class="o">==</span> <span class="p">{</span><span class="s1">'newkey'</span><span class="p">:</span> <span class="s1">'newvalue'</span><span class="p">}</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">foo</span> <span class="o">==</span> <span class="n">original</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Mock支持 Python <a class="reference internal" href="#magic-methods"><span class="std std-ref">魔术方法</span></a> 。使用模式方法最简单的方式是使用 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> class. 。它可以做如下事情:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__str__</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="s1">'foobarbaz'</span>
|
||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">'foobarbaz'</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__str__</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Mock 能指定函数(或其他 Mock 实例)为魔术方法,它们将被适当地调用。 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 是预先创建了所有魔术方法(所有有用的方法) 的 Mock 。</p>
|
||
<p>下面是一个使用了普通 Mock 类的魔术方法的例子</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__str__</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="s1">'wheeeeee'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">'wheeeeee'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>使用 <a class="reference internal" href="#auto-speccing"><span class="std std-ref">auto-speccing</span></a> 可以保证测试中的模拟对象与要替换的对象具有相同的api 。在 patch 中可以通过 <em>autospec</em> 参数实现自动推断,或者使用 <a class="reference internal" href="#unittest.mock.create_autospec" title="unittest.mock.create_autospec"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_autospec()</span></code></a> 函数。自动推断会创建一个与要替换对象相同的属相和方法的模拟对象,并且任何函数和方法(包括构造函数)都具有与真实对象相同的调用签名。</p>
|
||
<p>这么做是为了因确保不当地使用 mock 导致与生产代码相同的失败:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">unittest.mock</span> <span class="kn">import</span> <span class="n">create_autospec</span>
|
||
<span class="gp">>>> </span><span class="k">def</span> <span class="nf">function</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">pass</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock_function</span> <span class="o">=</span> <span class="n">create_autospec</span><span class="p">(</span><span class="n">function</span><span class="p">,</span> <span class="n">return_value</span><span class="o">=</span><span class="s1">'fishy'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock_function</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="go">'fishy'</span>
|
||
<span class="gp">>>> </span><span class="n">mock_function</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock_function</span><span class="p">(</span><span class="s1">'wrong arguments'</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">TypeError</span>: <span class="n"><lambda>() takes exactly 3 arguments (1 given)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在类中使用 <a class="reference internal" href="#unittest.mock.create_autospec" title="unittest.mock.create_autospec"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_autospec()</span></code></a> 时,会复制 <code class="docutils literal notranslate"><span class="pre">__init__</span></code> 的签名,另外在可调用对象上使用时,会复制 <code class="docutils literal notranslate"><span class="pre">__call__</span></code> 的签名。</p>
|
||
</section>
|
||
<section id="the-mock-class">
|
||
<h2>Mock 类<a class="headerlink" href="#the-mock-class" title="永久链接至标题">¶</a></h2>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 是一个可以灵活的替换存根 (stubs) 的对象,可以测试所有代码。 Mock 是可调用的,在访问其属性时创建一个新的 mock <a class="footnote-reference brackets" href="#id3" id="id1">1</a> 。访问相同的属性只会返回相同的 mock 。 Mock 保存调用记录,可以通过断言获悉代码的调用。</p>
|
||
<p><a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 是 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 的子类,它有所有预创建且可使用的魔术方法。在需要模拟不可调用对象时,可以使用 <a class="reference internal" href="#unittest.mock.NonCallableMock" title="unittest.mock.NonCallableMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">NonCallableMock</span></code></a> 和 <a class="reference internal" href="#unittest.mock.NonCallableMagicMock" title="unittest.mock.NonCallableMagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">NonCallableMagicMock</span></code></a></p>
|
||
<p><a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 装饰器使得用 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 对象临时替换特定模块中的类非常方便。 默认情况下 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 将为你创建一个 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a>。 你可以使用 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 的 <em>new_callable</em> 参数指定替代 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 的类。</p>
|
||
<dl class="class">
|
||
<dt id="unittest.mock.Mock">
|
||
<em class="property">class </em><code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">Mock</code><span class="sig-paren">(</span><em class="sig-param">spec=None</em>, <em class="sig-param">side_effect=None</em>, <em class="sig-param">return_value=DEFAULT</em>, <em class="sig-param">wraps=None</em>, <em class="sig-param">name=None</em>, <em class="sig-param">spec_set=None</em>, <em class="sig-param">unsafe=False</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建一个新的 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 对象。通过可选参数指定 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 对象的行为:</p>
|
||
<ul>
|
||
<li><p><em>spec</em>: 可以是要给字符串列表,也可以是充当模拟对象规范的现有对象(类或实例)。如果传入一个对象,则通过在该对象上调用 dir 来生成字符串列表(不支持的魔法属性和方法除外)。访问不在此列表中的任何属性都将引发 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a> 。</p>
|
||
<p>如果 <em>spec</em> 是一个对象(而不是字符串列表),则 <a class="reference internal" href="stdtypes.html#instance.__class__" title="instance.__class__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__class__</span></code></a> 返回 <em>spec</em> 对象的类。 这允许模拟程序通过 <a class="reference internal" href="functions.html#isinstance" title="isinstance"><code class="xref py py-func docutils literal notranslate"><span class="pre">isinstance()</span></code></a> 测试。</p>
|
||
</li>
|
||
<li><p><em>spec_set</em> :<em>spec</em> 的更严格的变体。如果使用了该属性,尝试模拟 <em>set</em> 或 <em>get</em> 的属性不在 <em>spec_set</em> 所包含的对象中时,会抛出 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a> 。</p></li>
|
||
<li><p><em>side_effect</em> :每当调用 Mock 时都会调用的函数。 参见 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 属性。 对于引发异常或动态更改返回值很有用。 该函数使用与 mock 函数相同的参数调用,并且除非返回 <a class="reference internal" href="#unittest.mock.DEFAULT" title="unittest.mock.DEFAULT"><code class="xref py py-data docutils literal notranslate"><span class="pre">DEFAULT</span></code></a> ,否则该函数的返回值将用作返回值。</p>
|
||
<p>另外, <em>side_effect</em> 可以是异常类或实例。 此时,调用模拟程序时将引发异常。</p>
|
||
<p>如果 <em>side_effect</em> 是可迭代对象,则每次调用 mock 都将返回可迭代对象的下一个值。</p>
|
||
<p>设置 <em>side_effect</em> 为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 即可清空。</p>
|
||
</li>
|
||
<li><p><em>return_value</em> :调用 mock 的返回值。 默认情况下,是一个新的Mock(在首次访问时创建)。 参见 <a class="reference internal" href="#unittest.mock.Mock.return_value" title="unittest.mock.Mock.return_value"><code class="xref py py-attr docutils literal notranslate"><span class="pre">return_value</span></code></a> 属性 。</p></li>
|
||
<li><p><em>unsafe</em> :默认情况下,如果任何以 <em>assert</em> 或 <em>assret</em> 开头的属性都将引发 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a> 。 当 <code class="docutils literal notranslate"><span class="pre">unsafe=True</span></code> 时可以访问。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.5 新版功能.</span></p>
|
||
</div>
|
||
</li>
|
||
<li><p><em>wraps</em> :要包装的 mock 对象。 如果 <em>wraps</em> 不是 <code class="docutils literal notranslate"><span class="pre">None</span></code> ,那么调用 Mock 会将调用传递给 <em>wraps</em> 的对象(返回实际结果)。 对模拟的属性访问将返回一个 Mock 对象,该对象包装了 <em>wraps</em> 对象的相应属性(因此,尝试访问不存在的属性将引发 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a> )。</p>
|
||
<p>如果该 mock 明确指定 <em>return_value</em> ,调用是,不会返回包装对象,而是返回 <em>return_value</em> 。</p>
|
||
</li>
|
||
<li><p><em>name</em> :mock 的名称。 在调试时很有用。 名称会传递到子 mock 。</p></li>
|
||
</ul>
|
||
<p>还可以使用任意关键字参数来调用 mock 。 创建模拟后,将使用这些属性来设置 mock 的属性。 有关详细信息,请参见 <a class="reference internal" href="#unittest.mock.Mock.configure_mock" title="unittest.mock.Mock.configure_mock"><code class="xref py py-meth docutils literal notranslate"><span class="pre">configure_mock()</span></code></a> 方法。</p>
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.assert_called">
|
||
<code class="sig-name descname">assert_called</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.assert_called" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言该 mock 至少被调用过一次。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="p">()</span>
|
||
<span class="go"><Mock name='mock.method()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="o">.</span><span class="n">assert_called</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.6 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.assert_called_once">
|
||
<code class="sig-name descname">assert_called_once</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.assert_called_once" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言仅被调用一次。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="p">()</span>
|
||
<span class="go"><Mock name='mock.method()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="o">.</span><span class="n">assert_called_once</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="p">()</span>
|
||
<span class="go"><Mock name='mock.method()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="o">.</span><span class="n">assert_called_once</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="c">...</span>
|
||
<span class="gr">AssertionError</span>: <span class="n">Expected 'method' to have been called once. Called 2 times.</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.6 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.assert_called_with">
|
||
<code class="sig-name descname">assert_called_with</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.assert_called_with" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>此方法是断言上次调用已以特定方式进行的一种便捷方法:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="n">test</span><span class="o">=</span><span class="s1">'wow'</span><span class="p">)</span>
|
||
<span class="go"><Mock name='mock.method()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="n">test</span><span class="o">=</span><span class="s1">'wow'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.assert_called_once_with">
|
||
<code class="sig-name descname">assert_called_once_with</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.assert_called_once_with" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言仅被调用一次,并且该调用是使用指定的参数进行的。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'baz'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'baz'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="s1">'other'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'values'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="s1">'other'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'values'</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">AssertionError</span>: <span class="n">Expected 'mock' to be called once. Called 2 times.</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.assert_any_call">
|
||
<code class="sig-name descname">assert_any_call</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.assert_any_call" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言使用指定的参数调用。</p>
|
||
<p>如果 mock <em>曾经</em> 被调用过则断言通过,不同于 <a class="reference internal" href="#unittest.mock.Mock.assert_called_with" title="unittest.mock.Mock.assert_called_with"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_called_with()</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.assert_called_once_with" title="unittest.mock.Mock.assert_called_once_with"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_called_once_with()</span></code></a> 那样只有在调用是最近的一次时才会通过,而对于 <a class="reference internal" href="#unittest.mock.Mock.assert_called_once_with" title="unittest.mock.Mock.assert_called_once_with"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_called_once_with()</span></code></a> 则它还必须是唯一的一次调用。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">arg</span><span class="o">=</span><span class="s1">'thing'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="s1">'some'</span><span class="p">,</span> <span class="s1">'thing'</span><span class="p">,</span> <span class="s1">'else'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_any_call</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">arg</span><span class="o">=</span><span class="s1">'thing'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.assert_has_calls">
|
||
<code class="sig-name descname">assert_has_calls</code><span class="sig-paren">(</span><em class="sig-param">calls</em>, <em class="sig-param">any_order=False</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.assert_has_calls" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言 mock 已附带指定的参数被调用。 将针对这些调用检查 <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 列表。</p>
|
||
<p>如果 <em>any_order</em> 为假值则调用必须是顺序进行的。 在指定的调用之前或之后还可以有额外的调用。</p>
|
||
<p>如果 <em>any_order</em> 为真值则调用可以是任意顺序的,但它们都必须在 <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 中出现。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">calls</span> <span class="o">=</span> <span class="p">[</span><span class="n">call</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="n">call</span><span class="p">(</span><span class="mi">3</span><span class="p">)]</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_has_calls</span><span class="p">(</span><span class="n">calls</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">calls</span> <span class="o">=</span> <span class="p">[</span><span class="n">call</span><span class="p">(</span><span class="mi">4</span><span class="p">),</span> <span class="n">call</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="n">call</span><span class="p">(</span><span class="mi">3</span><span class="p">)]</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_has_calls</span><span class="p">(</span><span class="n">calls</span><span class="p">,</span> <span class="n">any_order</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.assert_not_called">
|
||
<code class="sig-name descname">assert_not_called</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.assert_not_called" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言 mock 从未被调用过。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">hello</span><span class="o">.</span><span class="n">assert_not_called</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">obj</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">hello</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">hello</span><span class="o">.</span><span class="n">assert_not_called</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">AssertionError</span>: <span class="n">Expected 'hello' to not have been called. Called 1 times.</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.5 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.reset_mock">
|
||
<code class="sig-name descname">reset_mock</code><span class="sig-paren">(</span><em class="sig-param">*</em>, <em class="sig-param">return_value=False</em>, <em class="sig-param">side_effect=False</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.reset_mock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>reset_mock 方法将在 mock 对象上重围所有的调用属性:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="s1">'hello'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">called</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">reset_mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">called</span>
|
||
<span class="go">False</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.6 版更改: </span>向 reset_mock 函数添加了两个仅限关键字参数。</p>
|
||
</div>
|
||
<p>这在你想要创建一系列重用相同对象的断言时会很有用处。 请注意 <a class="reference internal" href="#unittest.mock.Mock.reset_mock" title="unittest.mock.Mock.reset_mock"><code class="xref py py-meth docutils literal notranslate"><span class="pre">reset_mock()</span></code></a> <em>不会</em> 清除返回值、<a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 或任何你使用普通赋值所默认设置的子属性。 如果你想要重置 <em>return_value</em> 或 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a>,则要为相应的形参传入 <code class="docutils literal notranslate"><span class="pre">True</span></code>。 子 mock 和返回值 mock (如果有的话) 也会被重置。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p><em>return_value</em> 和 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 均为仅限关键字参数。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.mock_add_spec">
|
||
<code class="sig-name descname">mock_add_spec</code><span class="sig-paren">(</span><em class="sig-param">spec</em>, <em class="sig-param">spec_set=False</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.mock_add_spec" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>为 mock 添加规格说明。 <em>spec</em> 可以是一个对象或字符串列表。 只有 <em>spec</em> 上的属性可以作为来自 mock 的属性被获取。</p>
|
||
<p>如果 <em>spec_set</em> 为真值则只有 spec 上的属性可以被设置。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.attach_mock">
|
||
<code class="sig-name descname">attach_mock</code><span class="sig-paren">(</span><em class="sig-param">mock</em>, <em class="sig-param">attribute</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.attach_mock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>附加一个 mock 作为这一个的属性,替换它的名称和上级。 对附加 mock 的调用将记录在这一个的 <a class="reference internal" href="#unittest.mock.Mock.method_calls" title="unittest.mock.Mock.method_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">method_calls</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 属性中。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.configure_mock">
|
||
<code class="sig-name descname">configure_mock</code><span class="sig-paren">(</span><em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.configure_mock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>通过关键字参数在 mock 上设置属性。</p>
|
||
<p>属性加返回值和附带影响可以使用标准点号标记在子 mock 上设置并在方法调用中解包一个字典:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">attrs</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'method.return_value'</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s1">'other.side_effect'</span><span class="p">:</span> <span class="ne">KeyError</span><span class="p">}</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">configure_mock</span><span class="p">(</span><span class="o">**</span><span class="n">attrs</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">other</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">KeyError</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>同样的操作可在对 mock 的构造器调用中达成:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">attrs</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'method.return_value'</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s1">'other.side_effect'</span><span class="p">:</span> <span class="ne">KeyError</span><span class="p">}</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">some_attribute</span><span class="o">=</span><span class="s1">'eggs'</span><span class="p">,</span> <span class="o">**</span><span class="n">attrs</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">some_attribute</span>
|
||
<span class="go">'eggs'</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">other</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">KeyError</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock.configure_mock" title="unittest.mock.Mock.configure_mock"><code class="xref py py-meth docutils literal notranslate"><span class="pre">configure_mock()</span></code></a> 的存在是使得 mock 被创建之后的配置更为容易。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock.__dir__">
|
||
<code class="sig-name descname">__dir__</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock.__dir__" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 对象会将 <code class="docutils literal notranslate"><span class="pre">dir(some_mock)</span></code> 的结果限制为有用结果。 对于带有 <em>spec</em> 的 mock 这还包括 mock 的所有被允许的属性。</p>
|
||
<p>请查看 <a class="reference internal" href="#unittest.mock.FILTER_DIR" title="unittest.mock.FILTER_DIR"><code class="xref py py-data docutils literal notranslate"><span class="pre">FILTER_DIR</span></code></a> 了解此过滤做了什么,以及如何停用它。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.Mock._get_child_mock">
|
||
<code class="sig-name descname">_get_child_mock</code><span class="sig-paren">(</span><em class="sig-param">**kw</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.Mock._get_child_mock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建针对属性和返回值的子 mock。 默认情况下子 mock 将为与其上级相同的类型。 Mock 的子类可能需要重载它来定制子 mock 的创建方式。</p>
|
||
<p>对于非可调用的 mock 将会使用可调用的变化形式(而非不是任意的自定义子类)。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.Mock.called">
|
||
<code class="sig-name descname">called</code><a class="headerlink" href="#unittest.mock.Mock.called" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>一个表示 mock 对象是否已被调用的布尔值:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">called</span>
|
||
<span class="go">False</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">called</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.Mock.call_count">
|
||
<code class="sig-name descname">call_count</code><a class="headerlink" href="#unittest.mock.Mock.call_count" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>一个告诉你 mock object 对象已被调用多少次的整数值:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_count</span>
|
||
<span class="go">0</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_count</span>
|
||
<span class="go">2</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.Mock.return_value">
|
||
<code class="sig-name descname">return_value</code><a class="headerlink" href="#unittest.mock.Mock.return_value" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>设置这个来配置通过调用该 mock 所返回的值:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="s1">'fish'</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="go">'fish'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>默认的返回值是一个 mock 对象并且你可以通过正常方式来配置它:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">return_value</span><span class="o">.</span><span class="n">attribute</span> <span class="o">=</span> <span class="n">sentinel</span><span class="o">.</span><span class="n">Attribute</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">return_value</span><span class="p">()</span>
|
||
<span class="go"><Mock name='mock()()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">return_value</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock.return_value" title="unittest.mock.Mock.return_value"><code class="xref py py-attr docutils literal notranslate"><span class="pre">return_value</span></code></a> 也可以在构造器中设置:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">return_value</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.Mock.side_effect">
|
||
<code class="sig-name descname">side_effect</code><a class="headerlink" href="#unittest.mock.Mock.side_effect" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>这可以是当该This can either be a function to be called when the mock 被调用时将被调用的一个函数,可调用对象或者要被引发的异常(类或实例)。</p>
|
||
<p>如果你传入一个函数则它将附带与该 mock 相同的参数被调用并且除了该函数返回 <a class="reference internal" href="#unittest.mock.DEFAULT" title="unittest.mock.DEFAULT"><code class="xref py py-data docutils literal notranslate"><span class="pre">DEFAULT</span></code></a> 单例的情况以外对该 mock 的调用都将随后返回该函数所返回的任何东西。 如果该函数返回 <a class="reference internal" href="#unittest.mock.DEFAULT" title="unittest.mock.DEFAULT"><code class="xref py py-data docutils literal notranslate"><span class="pre">DEFAULT</span></code></a> 则该 mock 将返回其正常值 (来自 <a class="reference internal" href="#unittest.mock.Mock.return_value" title="unittest.mock.Mock.return_value"><code class="xref py py-attr docutils literal notranslate"><span class="pre">return_value</span></code></a>)。</p>
|
||
<p>如果你传入一个可迭代对象,它会被用来获取一个在每次调用时必须产生一个值的迭代器。 这个值可以是一个要被引发的异常实例,或是一个要从该调用返回给 mock 的值 (<a class="reference internal" href="#unittest.mock.DEFAULT" title="unittest.mock.DEFAULT"><code class="xref py py-data docutils literal notranslate"><span class="pre">DEFAULT</span></code></a> 处理与函数的情况一致)。</p>
|
||
<p>一个引发异常(来测试 API 的异常处理)的 mock 的示例:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="ne">Exception</span><span class="p">(</span><span class="s1">'Boom!'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">Exception</span>: <span class="n">Boom!</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>使用 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 来返回包含多个值的序列:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(),</span> <span class="n">mock</span><span class="p">(),</span> <span class="n">mock</span><span class="p">()</span>
|
||
<span class="go">(3, 2, 1)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>使用一个可调用对象:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="k">def</span> <span class="nf">side_effect</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">DEFAULT</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="n">side_effect</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 可以在构造器中设置。 下面是在 mock 被调用时增加一个该属性值并返回它的例子:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">side_effect</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">value</span><span class="p">:</span> <span class="n">value</span> <span class="o">+</span> <span class="mi">1</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">side_effect</span><span class="o">=</span><span class="n">side_effect</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="go">4</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="o">-</span><span class="mi">8</span><span class="p">)</span>
|
||
<span class="go">-7</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>将 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 设为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 可以清除它:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">side_effect</span><span class="o">=</span><span class="ne">KeyError</span><span class="p">,</span> <span class="n">return_value</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">KeyError</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.Mock.call_args">
|
||
<code class="sig-name descname">call_args</code><a class="headerlink" href="#unittest.mock.Mock.call_args" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>这可以是 <code class="docutils literal notranslate"><span class="pre">None</span></code> (如果 mock 没有被调用),或是 mock 最近一次被调用时附带的参数。 这将采用元组的形式:第一个成员也可以通过 <code class="docutils literal notranslate"><span class="pre">args</span></code> 特征属性来访问,它是 mock 被调用时所附带的任何位置参数 (或为空元组),而第二个成员也可以通过 <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> 特征属性来访问,它则是任何关键字参数 (或为空字典)。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">mock</span><span class="o">.</span><span class="n">call_args</span><span class="p">)</span>
|
||
<span class="go">None</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args</span>
|
||
<span class="go">call()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args</span> <span class="o">==</span> <span class="p">()</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args</span>
|
||
<span class="go">call(3, 4)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args</span> <span class="o">==</span> <span class="p">((</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">),)</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args</span><span class="o">.</span><span class="n">args</span>
|
||
<span class="go">(3, 4)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args</span><span class="o">.</span><span class="n">kwargs</span>
|
||
<span class="go">{}</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s1">'fish'</span><span class="p">,</span> <span class="nb">next</span><span class="o">=</span><span class="s1">'w00t!'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args</span>
|
||
<span class="go">call(3, 4, 5, key='fish', next='w00t!')</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args</span><span class="o">.</span><span class="n">args</span>
|
||
<span class="go">(3, 4, 5)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args</span><span class="o">.</span><span class="n">kwargs</span>
|
||
<span class="go">{'key': 'fish', 'next': 'w00t!'}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock.call_args" title="unittest.mock.Mock.call_args"><code class="xref py py-attr docutils literal notranslate"><span class="pre">call_args</span></code></a>,以及列表 <a class="reference internal" href="#unittest.mock.Mock.call_args_list" title="unittest.mock.Mock.call_args_list"><code class="xref py py-attr docutils literal notranslate"><span class="pre">call_args_list</span></code></a>, <a class="reference internal" href="#unittest.mock.Mock.method_calls" title="unittest.mock.Mock.method_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">method_calls</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 的成员都是 <a class="reference internal" href="#unittest.mock.call" title="unittest.mock.call"><code class="xref py py-data docutils literal notranslate"><span class="pre">call</span></code></a> 对象。 这些对象属性元组,因此它们可被解包以获得单独的参数并创建更复杂的断言。 参见 <a class="reference internal" href="#calls-as-tuples"><span class="std std-ref">作为元组的 call</span></a>。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>增加了 <code class="docutils literal notranslate"><span class="pre">args</span></code> 和 <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> 特征属性。properties.</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.Mock.call_args_list">
|
||
<code class="sig-name descname">call_args_list</code><a class="headerlink" href="#unittest.mock.Mock.call_args_list" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>这是一个已排序的对 mock 对象的所有调用的列表(因此该列表的长度就是它已被调用的次数)。 在执行任何调用之前它将是一个空列表。 <a class="reference internal" href="#unittest.mock.call" title="unittest.mock.call"><code class="xref py py-data docutils literal notranslate"><span class="pre">call</span></code></a> 对象可以被用来方便地构造调用列表以与 <a class="reference internal" href="#unittest.mock.Mock.call_args_list" title="unittest.mock.Mock.call_args_list"><code class="xref py py-attr docutils literal notranslate"><span class="pre">call_args_list</span></code></a> 相比较。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s1">'fish'</span><span class="p">,</span> <span class="nb">next</span><span class="o">=</span><span class="s1">'w00t!'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args_list</span>
|
||
<span class="go">[call(), call(3, 4), call(key='fish', next='w00t!')]</span>
|
||
<span class="gp">>>> </span><span class="n">expected</span> <span class="o">=</span> <span class="p">[(),</span> <span class="p">((</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">),),</span> <span class="p">({</span><span class="s1">'key'</span><span class="p">:</span> <span class="s1">'fish'</span><span class="p">,</span> <span class="s1">'next'</span><span class="p">:</span> <span class="s1">'w00t!'</span><span class="p">},)]</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">call_args_list</span> <span class="o">==</span> <span class="n">expected</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock.call_args_list" title="unittest.mock.Mock.call_args_list"><code class="xref py py-attr docutils literal notranslate"><span class="pre">call_args_list</span></code></a> 的成员均为 <a class="reference internal" href="#unittest.mock.call" title="unittest.mock.call"><code class="xref py py-data docutils literal notranslate"><span class="pre">call</span></code></a> 对象。 它们可作为元组被解包以获得单个参数。 参见 <a class="reference internal" href="#calls-as-tuples"><span class="std std-ref">作为元组的 call</span></a>。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.Mock.method_calls">
|
||
<code class="sig-name descname">method_calls</code><a class="headerlink" href="#unittest.mock.Mock.method_calls" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>除了会追踪对其自身的调用,mock 还会追踪对方法和属性,以及 <em>它们的</em> 方法和属性的访问:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="p">()</span>
|
||
<span class="go"><Mock name='mock.method()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">property</span><span class="o">.</span><span class="n">method</span><span class="o">.</span><span class="n">attribute</span><span class="p">()</span>
|
||
<span class="go"><Mock name='mock.property.method.attribute()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method_calls</span>
|
||
<span class="go">[call.method(), call.property.method.attribute()]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock.method_calls" title="unittest.mock.Mock.method_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">method_calls</span></code></a> 的成员均为 <a class="reference internal" href="#unittest.mock.call" title="unittest.mock.call"><code class="xref py py-data docutils literal notranslate"><span class="pre">call</span></code></a> 对象。 它们可以作为元组被解包以获得单个参数。 参见 <a class="reference internal" href="#calls-as-tuples"><span class="std std-ref">作为元组的 call</span></a>.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.Mock.mock_calls">
|
||
<code class="sig-name descname">mock_calls</code><a class="headerlink" href="#unittest.mock.Mock.mock_calls" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 会记录 <em>所有</em> 对 mock 对象、它的方法、魔术方法的调用 <em>以及</em> 返回值的 mock。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">result</span> <span class="o">=</span> <span class="n">mock</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">first</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="go"><MagicMock name='mock.first()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">second</span><span class="p">()</span>
|
||
<span class="go"><MagicMock name='mock.second()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="nb">int</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">1</span>
|
||
<span class="gp">>>> </span><span class="n">result</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||
<span class="go"><MagicMock name='mock()()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">expected</span> <span class="o">=</span> <span class="p">[</span><span class="n">call</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="n">call</span><span class="o">.</span><span class="n">first</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="mi">3</span><span class="p">),</span> <span class="n">call</span><span class="o">.</span><span class="n">second</span><span class="p">(),</span>
|
||
<span class="gp">... </span><span class="n">call</span><span class="o">.</span><span class="fm">__int__</span><span class="p">(),</span> <span class="n">call</span><span class="p">()(</span><span class="mi">1</span><span class="p">)]</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">mock_calls</span> <span class="o">==</span> <span class="n">expected</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 的成员均为 <a class="reference internal" href="#unittest.mock.call" title="unittest.mock.call"><code class="xref py py-data docutils literal notranslate"><span class="pre">call</span></code></a> 对象。 它们可以作为元组被解包以获得单个参数。 参见 <a class="reference internal" href="#calls-as-tuples"><span class="std std-ref">作为元组的 call</span></a>。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 的记录方式意味着在进行嵌套调用时,之前调用的形参不会被记录因而这样的比较将总是相等:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">top</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span><span class="o">.</span><span class="n">bottom</span><span class="p">()</span>
|
||
<span class="go"><MagicMock name='mock.top().bottom()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">mock_calls</span>
|
||
<span class="go">[call.top(a=3), call.top().bottom()]</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">mock_calls</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">call</span><span class="o">.</span><span class="n">top</span><span class="p">(</span><span class="n">a</span><span class="o">=-</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">bottom</span><span class="p">()</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.Mock.__class__">
|
||
<code class="sig-name descname">__class__</code><a class="headerlink" href="#unittest.mock.Mock.__class__" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>通常一个对象的 <a class="reference internal" href="#unittest.mock.Mock.__class__" title="unittest.mock.Mock.__class__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__class__</span></code></a> 属性将返回其类型。 对于具有 <code class="xref py py-attr docutils literal notranslate"><span class="pre">spec</span></code> 的 mock 对象来说,<code class="docutils literal notranslate"><span class="pre">__class__</span></code> 将改为返回 spec 类。 这将允许 mock 对象为它们所替换 / 屏蔽的对象跳过 <a class="reference internal" href="functions.html#isinstance" title="isinstance"><code class="xref py py-func docutils literal notranslate"><span class="pre">isinstance()</span></code></a> 测试:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">spec</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">mock</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock.__class__" title="unittest.mock.Mock.__class__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__class__</span></code></a> 是可以被赋值的,这将允许 mock 跳过 <a class="reference internal" href="functions.html#isinstance" title="isinstance"><code class="xref py py-func docutils literal notranslate"><span class="pre">isinstance()</span></code></a> 检测而不强制要求你使用 spec:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="vm">__class__</span> <span class="o">=</span> <span class="nb">dict</span>
|
||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">mock</span><span class="p">,</span> <span class="nb">dict</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="unittest.mock.NonCallableMock">
|
||
<em class="property">class </em><code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">NonCallableMock</code><span class="sig-paren">(</span><em class="sig-param">spec=None</em>, <em class="sig-param">wraps=None</em>, <em class="sig-param">name=None</em>, <em class="sig-param">spec_set=None</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.NonCallableMock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>不可调用的 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 版本。 其构造器的形参具有与 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 相同的含义,区别在于 <em>return_value</em> 和 <em>side_effect</em> 在不可调用的 mock 上没有意义。</p>
|
||
</dd></dl>
|
||
|
||
<p>使用类或实例作为 <code class="xref py py-attr docutils literal notranslate"><span class="pre">spec</span></code> 或 <code class="xref py py-attr docutils literal notranslate"><span class="pre">spec_set</span></code> 的 mock 对象能够跳过 <a class="reference internal" href="functions.html#isinstance" title="isinstance"><code class="xref py py-func docutils literal notranslate"><span class="pre">isinstance()</span></code></a> 测试:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">spec</span><span class="o">=</span><span class="n">SomeClass</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">mock</span><span class="p">,</span> <span class="n">SomeClass</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">spec_set</span><span class="o">=</span><span class="n">SomeClass</span><span class="p">())</span>
|
||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">mock</span><span class="p">,</span> <span class="n">SomeClass</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 类具有对模拟魔术方法的支持。 请参阅 <a class="reference internal" href="#magic-methods"><span class="std std-ref">魔术方法</span></a> 了解完整细节。</p>
|
||
<p>mock 操作类和 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 装饰器都接受任意关键字参数用于配置。 对于 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 装饰器来说关键字参数会被传给所创建 mock 的构造器。 这些关键字被用于配置 mock 的属性:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">attribute</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">other</span><span class="o">=</span><span class="s1">'fish'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">attribute</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">other</span>
|
||
<span class="go">'fish'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>子 mock 的返回值和附带效果也可使用带点号的标记通过相同的方式来设置。 由于你无法直接在调用中使用带点号的名称因此你需要创建一个字典并使用 <code class="docutils literal notranslate"><span class="pre">**</span></code> 来解包它:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">attrs</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'method.return_value'</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s1">'other.side_effect'</span><span class="p">:</span> <span class="ne">KeyError</span><span class="p">}</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">some_attribute</span><span class="o">=</span><span class="s1">'eggs'</span><span class="p">,</span> <span class="o">**</span><span class="n">attrs</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">some_attribute</span>
|
||
<span class="go">'eggs'</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">other</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">KeyError</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>使用 <em>spec</em> (或 <em>spec_set</em>) 创建的可调用 mock 将在匹配调用与 mock 时内省规格说明对象的签名。 因此,它可以匹配实际调用的参数而不必关心它们是按位置还是按名称传入的:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">):</span> <span class="k">pass</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">spec</span><span class="o">=</span><span class="n">f</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="go"><Mock name='mock()' id='140161580456576'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这适用于 <a class="reference internal" href="#unittest.mock.Mock.assert_called_with" title="unittest.mock.Mock.assert_called_with"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_called_with()</span></code></a>, <a class="reference internal" href="#unittest.mock.Mock.assert_called_once_with" title="unittest.mock.Mock.assert_called_once_with"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_called_once_with()</span></code></a>, <a class="reference internal" href="#unittest.mock.Mock.assert_has_calls" title="unittest.mock.Mock.assert_has_calls"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_has_calls()</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.assert_any_call" title="unittest.mock.Mock.assert_any_call"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_any_call()</span></code></a>。 当执行 <a class="reference internal" href="#auto-speccing"><span class="std std-ref">自动 spec</span></a> 时,它还将应用于 mock 对象的方法调用。</p>
|
||
<blockquote>
|
||
<div><div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.4 版更改: </span>添加了在附带规格说明和自动规格说明的 mock 对象上的签名内省</p>
|
||
</div>
|
||
</div></blockquote>
|
||
<dl class="class">
|
||
<dt id="unittest.mock.PropertyMock">
|
||
<em class="property">class </em><code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">PropertyMock</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.PropertyMock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>旨在作为类的特征属性或其他描述器使用的 mock。 <a class="reference internal" href="#unittest.mock.PropertyMock" title="unittest.mock.PropertyMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">PropertyMock</span></code></a> 提供了 <a class="reference internal" href="../reference/datamodel.html#object.__get__" title="object.__get__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__get__()</span></code></a> 和 <a class="reference internal" href="../reference/datamodel.html#object.__set__" title="object.__set__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__set__()</span></code></a> 方法以便你可以在它被提取时指定一个返回值。</p>
|
||
<p>当从一个对象提取 <a class="reference internal" href="#unittest.mock.PropertyMock" title="unittest.mock.PropertyMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">PropertyMock</span></code></a> 实例时将不附带任何参数地调用该 mock。 如果设置它则调用该 mock 时将附带被设置的值。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Foo</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="nd">@property</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="s1">'something'</span>
|
||
<span class="gp">... </span> <span class="nd">@foo</span><span class="o">.</span><span class="n">setter</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">pass</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.Foo.foo'</span><span class="p">,</span> <span class="n">new_callable</span><span class="o">=</span><span class="n">PropertyMock</span><span class="p">)</span> <span class="k">as</span> <span class="n">mock_foo</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="n">mock_foo</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="s1">'mockity-mock'</span>
|
||
<span class="gp">... </span> <span class="n">this_foo</span> <span class="o">=</span> <span class="n">Foo</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">this_foo</span><span class="o">.</span><span class="n">foo</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="n">this_foo</span><span class="o">.</span><span class="n">foo</span> <span class="o">=</span> <span class="mi">6</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">mockity-mock</span>
|
||
<span class="gp">>>> </span><span class="n">mock_foo</span><span class="o">.</span><span class="n">mock_calls</span>
|
||
<span class="go">[call(), call(6)]</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<p>由于 mock 属性的存储方式你无法直接将 <a class="reference internal" href="#unittest.mock.PropertyMock" title="unittest.mock.PropertyMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">PropertyMock</span></code></a> 附加到一个 mock 对象。 但是你可以将它附加到 mock 类型对象:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">p</span> <span class="o">=</span> <span class="n">PropertyMock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">type</span><span class="p">(</span><span class="n">m</span><span class="p">)</span><span class="o">.</span><span class="n">foo</span> <span class="o">=</span> <span class="n">p</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">foo</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">p</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<dl class="class">
|
||
<dt id="unittest.mock.AsyncMock">
|
||
<em class="property">class </em><code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">AsyncMock</code><span class="sig-paren">(</span><em class="sig-param">spec=None</em>, <em class="sig-param">side_effect=None</em>, <em class="sig-param">return_value=DEFAULT</em>, <em class="sig-param">wraps=None</em>, <em class="sig-param">name=None</em>, <em class="sig-param">spec_set=None</em>, <em class="sig-param">unsafe=False</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.AsyncMock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>An asynchronous version of <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a>. The <a class="reference internal" href="#unittest.mock.AsyncMock" title="unittest.mock.AsyncMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncMock</span></code></a> object will
|
||
behave so the object is recognized as an async function, and the result of a
|
||
call is an awaitable.</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">iscoroutinefunction</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">inspect</span><span class="o">.</span><span class="n">isawaitable</span><span class="p">(</span><span class="n">mock</span><span class="p">())</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>调用 <code class="docutils literal notranslate"><span class="pre">mock()</span></code> 的结果是一个异步函数,它在被等待之后将具有 <code class="docutils literal notranslate"><span class="pre">side_effect</span></code> 或 <code class="docutils literal notranslate"><span class="pre">return_value</span></code> 的结果:</p>
|
||
<ul class="simple">
|
||
<li><p>如果 <code class="docutils literal notranslate"><span class="pre">side_effect</span></code> 是一个函数,则异步函数将返回该函数的结果,</p></li>
|
||
<li><p>如果 <code class="docutils literal notranslate"><span class="pre">side_effect</span></code> 是一个异常,则异步函数将引发该异常,</p></li>
|
||
<li><p>如果 <code class="docutils literal notranslate"><span class="pre">side_effect</span></code> 是一个可迭代对象,则异步函数将返回该可迭代对象的下一个值,但是,如果结果序列被耗尽,则会立即引发 <code class="docutils literal notranslate"><span class="pre">StopAsyncIteration</span></code>,</p></li>
|
||
<li><p>如果 <code class="docutils literal notranslate"><span class="pre">side_effect</span></code> 未被定义,则异步函数将返回is not defined, the async function will return the value defined by <code class="docutils literal notranslate"><span class="pre">return_value</span></code> 所定义的值,因而,在默认情况下,异步函数会返回一个新的 <a class="reference internal" href="#unittest.mock.AsyncMock" title="unittest.mock.AsyncMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncMock</span></code></a> 对象。</p></li>
|
||
</ul>
|
||
<p>将 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 或 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 的 <em>spec</em> 设为异步函数将导致在调用后返回一个协程对象。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">async</span> <span class="k">def</span> <span class="nf">async_func</span><span class="p">():</span> <span class="k">pass</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">async_func</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span>
|
||
<span class="go"><MagicMock spec='function' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">()</span>
|
||
<span class="go"><coroutine object AsyncMockMixin._mock_call at ...></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>将 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a>, <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 或 <a class="reference internal" href="#unittest.mock.AsyncMock" title="unittest.mock.AsyncMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncMock</span></code></a> 的 <em>spec</em> 设为带有异步和同步函数的类将自动删除其中的同步函数并将它们设为 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> (如果上级 mock 是 <a class="reference internal" href="#unittest.mock.AsyncMock" title="unittest.mock.AsyncMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncMock</span></code></a> 或 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a>) 或者 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> (如果上级 mock 是 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a>)。 所有异步函数都将为 <a class="reference internal" href="#unittest.mock.AsyncMock" title="unittest.mock.AsyncMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncMock</span></code></a>。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">ExampleClass</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">sync_foo</span><span class="p">():</span>
|
||
<span class="gp">... </span> <span class="k">pass</span>
|
||
<span class="gp">... </span> <span class="k">async</span> <span class="k">def</span> <span class="nf">async_foo</span><span class="p">():</span>
|
||
<span class="gp">... </span> <span class="k">pass</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">a_mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">(</span><span class="n">ExampleClass</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">a_mock</span><span class="o">.</span><span class="n">sync_foo</span>
|
||
<span class="go"><MagicMock name='mock.sync_foo' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">a_mock</span><span class="o">.</span><span class="n">async_foo</span>
|
||
<span class="go"><AsyncMock name='mock.async_foo' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">ExampleClass</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">sync_foo</span>
|
||
<span class="go"><Mock name='mock.sync_foo' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">async_foo</span>
|
||
<span class="go"><AsyncMock name='mock.async_foo' id='...'></span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.8 新版功能.</span></p>
|
||
</div>
|
||
<dl class="method">
|
||
<dt id="unittest.mock.AsyncMock.assert_awaited">
|
||
<code class="sig-name descname">assert_awaited</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.AsyncMock.assert_awaited" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言 mock 已被等待至少一次。 请注意这是从被调用的对象中分离出来的,必须要使用 <code class="docutils literal notranslate"><span class="pre">await</span></code> 关键字:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">coroutine_mock</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">await</span> <span class="n">coroutine_mock</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">coroutine_mock</span> <span class="o">=</span> <span class="n">mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">called</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_awaited</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="c">...</span>
|
||
<span class="gr">AssertionError</span>: <span class="n">Expected mock to have been awaited.</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="n">coroutine_mock</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_awaited</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.AsyncMock.assert_awaited_once">
|
||
<code class="sig-name descname">assert_awaited_once</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.AsyncMock.assert_awaited_once" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言 mock 已被等待恰好一次。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
|
||
<span class="gp">... </span> <span class="k">await</span> <span class="n">mock</span><span class="p">()</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_awaited_once</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">method</span><span class="o">.</span><span class="n">assert_awaited_once</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="c">...</span>
|
||
<span class="gr">AssertionError</span>: <span class="n">Expected mock to have been awaited once. Awaited 2 times.</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.AsyncMock.assert_awaited_with">
|
||
<code class="sig-name descname">assert_awaited_with</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.AsyncMock.assert_awaited_with" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言上一次等待传入了指定的参数。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">await</span> <span class="n">mock</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_awaited_with</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_awaited_with</span><span class="p">(</span><span class="s1">'other'</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="c">...</span>
|
||
<span class="gr">AssertionError</span>: <span class="n">expected call not found.</span>
|
||
<span class="x">Expected: mock('other')</span>
|
||
<span class="x">Actual: mock('foo', bar='bar')</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.AsyncMock.assert_awaited_once_with">
|
||
<code class="sig-name descname">assert_awaited_once_with</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.AsyncMock.assert_awaited_once_with" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言 mock 被等待恰好一次并且附带了指定的参数。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">await</span> <span class="n">mock</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_awaited_once_with</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_awaited_once_with</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="c">...</span>
|
||
<span class="gr">AssertionError</span>: <span class="n">Expected mock to have been awaited once. Awaited 2 times.</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.AsyncMock.assert_any_await">
|
||
<code class="sig-name descname">assert_any_await</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.AsyncMock.assert_any_await" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言 mock 已被等待并附带了指定的参数。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">await</span> <span class="n">mock</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'hello'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_any_await</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_any_await</span><span class="p">(</span><span class="s1">'other'</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="c">...</span>
|
||
<span class="gr">AssertionError</span>: <span class="n">mock('other') await not found</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.AsyncMock.assert_has_awaits">
|
||
<code class="sig-name descname">assert_has_awaits</code><span class="sig-paren">(</span><em class="sig-param">calls</em>, <em class="sig-param">any_order=False</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.AsyncMock.assert_has_awaits" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言 mock 已附带了指定的调用被等待。 将针对这些等待检查 <a class="reference internal" href="#unittest.mock.AsyncMock.await_args_list" title="unittest.mock.AsyncMock.await_args_list"><code class="xref py py-attr docutils literal notranslate"><span class="pre">await_args_list</span></code></a> 列表。</p>
|
||
<p>如果 <em>any_order</em> 为假值则等待必须是顺序进行的。 在指定的等待之前或之后还可以有额外的调用。</p>
|
||
<p>如果 <em>any_order</em> 为真值则等待可以是任意顺序的,但它们都必须在 <a class="reference internal" href="#unittest.mock.AsyncMock.await_args_list" title="unittest.mock.AsyncMock.await_args_list"><code class="xref py py-attr docutils literal notranslate"><span class="pre">await_args_list</span></code></a> 中出现。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">await</span> <span class="n">mock</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">calls</span> <span class="o">=</span> <span class="p">[</span><span class="n">call</span><span class="p">(</span><span class="s2">"foo"</span><span class="p">),</span> <span class="n">call</span><span class="p">(</span><span class="s2">"bar"</span><span class="p">)]</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_has_awaits</span><span class="p">(</span><span class="n">calls</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="c">...</span>
|
||
<span class="gr">AssertionError</span>: <span class="n">Awaits not found.</span>
|
||
<span class="x">Expected: [call('foo'), call('bar')]</span>
|
||
<span class="x">Actual: []</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'bar'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_has_awaits</span><span class="p">(</span><span class="n">calls</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.AsyncMock.assert_not_awaited">
|
||
<code class="sig-name descname">assert_not_awaited</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.AsyncMock.assert_not_awaited" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>断言 mock 从未被等待过。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_not_awaited</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.AsyncMock.reset_mock">
|
||
<code class="sig-name descname">reset_mock</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.AsyncMock.reset_mock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>参见 <a class="reference internal" href="#unittest.mock.Mock.reset_mock" title="unittest.mock.Mock.reset_mock"><code class="xref py py-func docutils literal notranslate"><span class="pre">Mock.reset_mock()</span></code></a>。 还会将 <a class="reference internal" href="#unittest.mock.AsyncMock.await_count" title="unittest.mock.AsyncMock.await_count"><code class="xref py py-attr docutils literal notranslate"><span class="pre">await_count</span></code></a> 设为 0,将 <a class="reference internal" href="#unittest.mock.AsyncMock.await_args" title="unittest.mock.AsyncMock.await_args"><code class="xref py py-attr docutils literal notranslate"><span class="pre">await_args</span></code></a> 设为 None,并清空 <a class="reference internal" href="#unittest.mock.AsyncMock.await_args_list" title="unittest.mock.AsyncMock.await_args_list"><code class="xref py py-attr docutils literal notranslate"><span class="pre">await_args_list</span></code></a>。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.AsyncMock.await_count">
|
||
<code class="sig-name descname">await_count</code><a class="headerlink" href="#unittest.mock.AsyncMock.await_count" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>一个追踪 mock 对象已被等待多少次的整数值。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
|
||
<span class="gp">... </span> <span class="k">await</span> <span class="n">mock</span><span class="p">()</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">await_count</span>
|
||
<span class="go">1</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">await_count</span>
|
||
<span class="go">2</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.AsyncMock.await_args">
|
||
<code class="sig-name descname">await_args</code><a class="headerlink" href="#unittest.mock.AsyncMock.await_args" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>这可能为 <code class="docutils literal notranslate"><span class="pre">None</span></code> (如果 mock 从未被等待),或为该 mock 上一次被等待所附带的参数。 其功能与 <a class="reference internal" href="#unittest.mock.Mock.call_args" title="unittest.mock.Mock.call_args"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Mock.call_args</span></code></a> 相同。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">await</span> <span class="n">mock</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">await_args</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">await_args</span>
|
||
<span class="go">call('foo')</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'bar'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">await_args</span>
|
||
<span class="go">call('bar')</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="unittest.mock.AsyncMock.await_args_list">
|
||
<code class="sig-name descname">await_args_list</code><a class="headerlink" href="#unittest.mock.AsyncMock.await_args_list" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>这是由对 mock 对象按顺序执行的所有等待组成的列表(因此该列表的长度即它被等待的次数)。 在有任何等待被执行之前它将为一个空列表。Before any awaits have been made it is an empty list.</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">AsyncMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">await</span> <span class="n">mock</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">await_args_list</span>
|
||
<span class="go">[]</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">await_args_list</span>
|
||
<span class="go">[call('foo')]</span>
|
||
<span class="gp">>>> </span><span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">main</span><span class="p">(</span><span class="s1">'bar'</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">await_args_list</span>
|
||
<span class="go">[call('foo'), call('bar')]</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
</dd></dl>
|
||
|
||
<section id="calling">
|
||
<h3>调用<a class="headerlink" href="#calling" title="永久链接至标题">¶</a></h3>
|
||
<p>Mock 对象是可调用对象。 调用将把值集合作为 <a class="reference internal" href="#unittest.mock.Mock.return_value" title="unittest.mock.Mock.return_value"><code class="xref py py-attr docutils literal notranslate"><span class="pre">return_value</span></code></a> 属性返回。 默认的返回值是一个新的 Mock 对象;它会在对返回值的首次访问(不论是显式访问还是通过调用 Mock)时被创建 —— 但它会被保存并且每次都返回相同的对象。</p>
|
||
<p>对该对象的调用将被记录在 <a class="reference internal" href="#unittest.mock.Mock.call_args" title="unittest.mock.Mock.call_args"><code class="xref py py-attr docutils literal notranslate"><span class="pre">call_args</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.call_args_list" title="unittest.mock.Mock.call_args_list"><code class="xref py py-attr docutils literal notranslate"><span class="pre">call_args_list</span></code></a> 等属性中。</p>
|
||
<p>如果设置了 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 则它将在调用被记录之后被调用,因此如果 <code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code> 引发了异常该调用仍然会被记录。</p>
|
||
<p>让一个 mock 在被调用时引发异常的最简单方式是将 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 设为一个异常类或实例:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">side_effect</span><span class="o">=</span><span class="ne">IndexError</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">IndexError</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">mock_calls</span>
|
||
<span class="go">[call(1, 2, 3)]</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="ne">KeyError</span><span class="p">(</span><span class="s1">'Bang!'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">(</span><span class="s1">'two'</span><span class="p">,</span> <span class="s1">'three'</span><span class="p">,</span> <span class="s1">'four'</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">KeyError</span>: <span class="n">'Bang!'</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">mock_calls</span>
|
||
<span class="go">[call(1, 2, 3), call('two', 'three', 'four')]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果 <code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code> 为函数则该函数所返回的对象就是调用该 mock 所返回的对象。 <code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code> 函数在被调用时将附带与该 mock 相同的参数。 这允许你根据输入动态地改变返回值:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">def</span> <span class="nf">side_effect</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">value</span> <span class="o">+</span> <span class="mi">1</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">side_effect</span><span class="o">=</span><span class="n">side_effect</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||
<span class="go">2</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">mock_calls</span>
|
||
<span class="go">[call(1), call(2)]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果你想让该 mock 仍然返回默认的返回值(一个新的 mock对象),或是任何设定的返回值,那么有两种方式可以做到这一点。 从 <code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code> 内部返回 <code class="xref py py-attr docutils literal notranslate"><span class="pre">mock.return_value</span></code>,或者返回 <a class="reference internal" href="#unittest.mock.DEFAULT" title="unittest.mock.DEFAULT"><code class="xref py py-data docutils literal notranslate"><span class="pre">DEFAULT</span></code></a>:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">def</span> <span class="nf">side_effect</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">m</span><span class="o">.</span><span class="n">return_value</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="n">side_effect</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="mi">3</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="k">def</span> <span class="nf">side_effect</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">DEFAULT</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="n">side_effect</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>要移除一个 <code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code>,并返回到默认的行为,请将 <code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code> 设为 <code class="docutils literal notranslate"><span class="pre">None</span></code>:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="mi">6</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="k">def</span> <span class="nf">side_effect</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="mi">3</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="n">side_effect</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="go">6</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code> 也可以是任意可迭代对象。 对该 mock 的重复调用将返回来自该可迭代对象的值(直到该可迭代对象被耗尽并导致 <a class="reference internal" href="exceptions.html#StopIteration" title="StopIteration"><code class="xref py py-exc docutils literal notranslate"><span class="pre">StopIteration</span></code></a> 被引发):</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">side_effect</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="go">1</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="go">2</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">StopIteration</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果该可迭代对象有任何成员属于异常则它们将被引发而不是被返回:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">iterable</span> <span class="o">=</span> <span class="p">(</span><span class="mi">33</span><span class="p">,</span> <span class="ne">ValueError</span><span class="p">,</span> <span class="mi">66</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">side_effect</span><span class="o">=</span><span class="n">iterable</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="go">33</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">ValueError</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="go">66</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="deleting-attributes">
|
||
<span id="id2"></span><h3>删除属性<a class="headerlink" href="#deleting-attributes" title="永久链接至标题">¶</a></h3>
|
||
<p>Mock 对象会根据需要创建属性。 这允许它们可以假装成任意类型的对象。</p>
|
||
<p>你可能想要一个 mock 对象在调用 <a class="reference internal" href="functions.html#hasattr" title="hasattr"><code class="xref py py-func docutils literal notranslate"><span class="pre">hasattr()</span></code></a> 时返回 <code class="docutils literal notranslate"><span class="pre">False</span></code>,或者在获取某个属性时引发 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a>。 你可以通过提供一个对象作为 mock 的 <code class="xref py py-attr docutils literal notranslate"><span class="pre">spec</span></code> 属性来做到这点,但这并不总是很方便。</p>
|
||
<p>你可以通过删除属性来“屏蔽”它们。 属性一旦被删除,访问它将引发 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a>。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="nb">hasattr</span><span class="p">(</span><span class="n">mock</span><span class="p">,</span> <span class="s1">'m'</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="k">del</span> <span class="n">mock</span><span class="o">.</span><span class="n">m</span>
|
||
<span class="gp">>>> </span><span class="nb">hasattr</span><span class="p">(</span><span class="n">mock</span><span class="p">,</span> <span class="s1">'m'</span><span class="p">)</span>
|
||
<span class="go">False</span>
|
||
<span class="gp">>>> </span><span class="k">del</span> <span class="n">mock</span><span class="o">.</span><span class="n">f</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">f</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="o">...</span>
|
||
<span class="gr">AttributeError</span>: <span class="n">f</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="mock-names-and-the-name-attribute">
|
||
<h3>Mock 的名称与 name 属性<a class="headerlink" href="#mock-names-and-the-name-attribute" title="永久链接至标题">¶</a></h3>
|
||
<p>由于 "name" 是 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 构造器的参数之一,如果你想让你的 mock 对象具有 "name" 属性你不可以在创建时传入该参数。 有两个替代方式。 一个选项是使用 <a class="reference internal" href="#unittest.mock.Mock.configure_mock" title="unittest.mock.Mock.configure_mock"><code class="xref py py-meth docutils literal notranslate"><span class="pre">configure_mock()</span></code></a>:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">configure_mock</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'my_name'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">name</span>
|
||
<span class="go">'my_name'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>一个更简单的选项是在 mock 创建之后简单地设置 "name" 属性:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s2">"foo"</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="attaching-mocks-as-attributes">
|
||
<h3>附加 Mock 作为属性<a class="headerlink" href="#attaching-mocks-as-attributes" title="永久链接至标题">¶</a></h3>
|
||
<p>当你附加一个 mock 作为另一个 mock 的属性(或作为返回值)时它会成为该 mock 的 "子对象"。 对子对象的调用会被记录在父对象的 <a class="reference internal" href="#unittest.mock.Mock.method_calls" title="unittest.mock.Mock.method_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">method_calls</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 属性中。 这适用于配置子 mock 然后将它们附加到父对象,或是将 mock 附加到将记录所有对子对象的调用的父对象上并允许你创建有关 mock 之间的调用顺序的断言:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">parent</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">child1</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">child2</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">parent</span><span class="o">.</span><span class="n">child1</span> <span class="o">=</span> <span class="n">child1</span>
|
||
<span class="gp">>>> </span><span class="n">parent</span><span class="o">.</span><span class="n">child2</span> <span class="o">=</span> <span class="n">child2</span>
|
||
<span class="gp">>>> </span><span class="n">child1</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">child2</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">parent</span><span class="o">.</span><span class="n">mock_calls</span>
|
||
<span class="go">[call.child1(1), call.child2(2)]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这里有一个例外情况是如果 mock 设置了名称。 这允许你在出于某些理由不希望其发生时避免 "父对象" 的影响。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">not_a_child</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'not-a-child'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">attribute</span> <span class="o">=</span> <span class="n">not_a_child</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">attribute</span><span class="p">()</span>
|
||
<span class="go"><MagicMock name='not-a-child()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">mock_calls</span>
|
||
<span class="go">[]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>通过 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 创建的 mock 会被自动赋予名称。 要将具有名称的 mock 附加到父对象上你应当使用 <a class="reference internal" href="#unittest.mock.Mock.attach_mock" title="unittest.mock.Mock.attach_mock"><code class="xref py py-meth docutils literal notranslate"><span class="pre">attach_mock()</span></code></a> 方法:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">thing1</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">thing2</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">parent</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.thing1'</span><span class="p">,</span> <span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="k">as</span> <span class="n">child1</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">with</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.thing2'</span><span class="p">,</span> <span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="k">as</span> <span class="n">child2</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="n">parent</span><span class="o">.</span><span class="n">attach_mock</span><span class="p">(</span><span class="n">child1</span><span class="p">,</span> <span class="s1">'child1'</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="n">parent</span><span class="o">.</span><span class="n">attach_mock</span><span class="p">(</span><span class="n">child2</span><span class="p">,</span> <span class="s1">'child2'</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="n">child1</span><span class="p">(</span><span class="s1">'one'</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="n">child2</span><span class="p">(</span><span class="s1">'two'</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">parent</span><span class="o">.</span><span class="n">mock_calls</span>
|
||
<span class="go">[call.child1('one'), call.child2('two')]</span>
|
||
</pre></div>
|
||
</div>
|
||
<dl class="footnote brackets">
|
||
<dt class="label" id="id3"><span class="brackets"><a class="fn-backref" href="#id1">1</a></span></dt>
|
||
<dd><p>仅有的例外是魔术方法和属性(其名称前后都带有双下划线)。 Mock 不会创建它们而是将引发 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a>。 这是因为解释器将会经常隐式地请求这些方法,并且在它准备接受一个魔术方法却得到一个新的 Mock 对象时会 <em>相当</em> 困惑。 如果你需要魔术方法支持请参阅 <a class="reference internal" href="#magic-methods"><span class="std std-ref">魔术方法</span></a>。</p>
|
||
</dd>
|
||
</dl>
|
||
</section>
|
||
</section>
|
||
<section id="the-patchers">
|
||
<h2>patch 装饰器<a class="headerlink" href="#the-patchers" title="永久链接至标题">¶</a></h2>
|
||
<p>patch 装饰器仅被用于在它们所装饰的函数作用域内部为对象添加补丁。 它们会自动为你执行去除补丁的处理,即使是在引发了异常的情况下。 所有这些函数都还可在 with 语句中使用或是作为类装饰器。</p>
|
||
<section id="patch">
|
||
<h3>patch<a class="headerlink" href="#patch" title="永久链接至标题">¶</a></h3>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p><a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> is straightforward to use. The key is to do the patching in the
|
||
right namespace. See the section <a class="reference internal" href="#id6">where to patch</a>.</p>
|
||
</div>
|
||
<dl class="function">
|
||
<dt id="unittest.mock.patch">
|
||
<code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">patch</code><span class="sig-paren">(</span><em class="sig-param">target</em>, <em class="sig-param">new=DEFAULT</em>, <em class="sig-param">spec=None</em>, <em class="sig-param">create=False</em>, <em class="sig-param">spec_set=None</em>, <em class="sig-param">autospec=None</em>, <em class="sig-param">new_callable=None</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.patch" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 可以作为函数装饰器、类装饰器或上下文管理器。 在函数或 with 语句的内部,<em>target</em> 会打上一个 <em>new</em> 对象补丁。 当函数/with 语句退出时补丁将被撤销。</p>
|
||
<p>如果 <em>new</em> 被省略,那么如果被打补丁的对象是一个异步函数则 target 将被替换为 <a class="reference internal" href="#unittest.mock.AsyncMock" title="unittest.mock.AsyncMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncMock</span></code></a> 否则替换为 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a>。 如果 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 被用作装饰器并且 <em>new</em> 被省略,那么已创建的 mock 将作为一个附加参数传入被装饰的函数。 如果 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 被用作上下文管理器那么已创建的 mock 将被该上下文管理器所返回。is returned by the context manager.</p>
|
||
<p><em>target</em> 应当为 <code class="docutils literal notranslate"><span class="pre">'package.module.ClassName'</span></code> 形式的字符串。 <em>target</em> 将被导入并且该指定对象会被替换为 <em>new</em> 对象,因此 <em>target</em> 必须是可以从你调用 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 的环境中导入的。 target 会在被装饰的函数被执行的时候被导入,而非在装饰的时候。</p>
|
||
<p><em>spec</em> 和 <em>spec_set</em> 关键字参数会被传递给 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a>,如果 patch 为你创建了此对象的话。</p>
|
||
<p>此外你还可以传入 <code class="docutils literal notranslate"><span class="pre">spec=True</span></code> 或 <code class="docutils literal notranslate"><span class="pre">spec_set=True</span></code>,这将使 patch 将被模拟的对象作为 spec/spec_set 对象传入。</p>
|
||
<p><em>new_callable</em> 允许你指定一个不同的类,或者可调用对象,它将被调用以创建 <em>新的</em> 对象。 在默认情况下将指定 <a class="reference internal" href="#unittest.mock.AsyncMock" title="unittest.mock.AsyncMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncMock</span></code></a> 用于异步函数,<a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 用于其他函数。</p>
|
||
<p>另一种更强形式的 <em>spec</em> 是 <em>autospec</em>。 如果你设置了 <code class="docutils literal notranslate"><span class="pre">autospec=True</span></code> 则将以来自被替换对象的 spec 来创建 mock。 mock 的所有属性也将具有被替换对象相应属性的 spec。 被模拟的方法和函数将检查它们的参数并且如果使用了错误的签名调用它们则将引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a>。 对于替换了一个类的 mock,它们的返回值(即‘实例’)将具有与该类相同的 spec。 请参阅 <a class="reference internal" href="#unittest.mock.create_autospec" title="unittest.mock.create_autospec"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_autospec()</span></code></a> 函数以及 <a class="reference internal" href="#auto-speccing"><span class="std std-ref">自动 spec</span></a>。</p>
|
||
<p>除了 <code class="docutils literal notranslate"><span class="pre">autospec=True</span></code> 你还可以传入 <code class="docutils literal notranslate"><span class="pre">autospec=some_object</span></code> 以使用任意对象而不是被替换的对象作为 spec。</p>
|
||
<p>在默认情况下 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 将无法替换不存在的属性。 如果你传入 <code class="docutils literal notranslate"><span class="pre">create=True</span></code>,且该属性并不存在,则 patch 将在调用被打补丁的函数时为你创建该属性,并在退出被打补丁的函数时再次删除它。 这适用于编写针对生产代码在运行时创建的属性的测试。 它默认是被关闭的因为这具有危险性。 当它被开启时你将能够针对实际上并不存在的 API 编写通过测试!</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.5 版更改: </span>如果你要给某个模块的内置函数打补丁则不必传入 <code class="docutils literal notranslate"><span class="pre">create=True</span></code>,它默认就会被添加。</p>
|
||
</div>
|
||
</div>
|
||
<p>Patch 可以被用作 <code class="xref py py-class docutils literal notranslate"><span class="pre">TestCase</span></code> 类装饰器。 其作用是装饰类中的每个测试方法。 当你的测试方法共享同一个补丁集时这将减少模板代码。 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 会通过查找以 <code class="docutils literal notranslate"><span class="pre">patch.TEST_PREFIX</span></code> 打头的名称来找到测试。 其默认值为 <code class="docutils literal notranslate"><span class="pre">'test'</span></code>,这与 <a class="reference internal" href="unittest.html#module-unittest" title="unittest: Unit testing framework for Python."><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest</span></code></a> 打到测试的方式一致。 你可以通过设置 <code class="docutils literal notranslate"><span class="pre">patch.TEST_PREFIX</span></code> 来指定其他的前缀。</p>
|
||
<p>Patch 可以通过 with 语句作为上下文管理器使用。 这时补丁将应用于 with 语句的缩进代码块。 如果你使用了 "as" 则打补丁的对象将被绑定到 "as" 之后的名称;这非常适用于当 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 为你创建 mock 对象的情况。</p>
|
||
<p><a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> takes arbitrary keyword arguments. These will be passed to
|
||
the <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> (or <em>new_callable</em>) on construction.</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">patch.dict(...)</span></code>, <code class="docutils literal notranslate"><span class="pre">patch.multiple(...)</span></code> 和 <code class="docutils literal notranslate"><span class="pre">patch.object(...)</span></code> 可用于其他使用场景。</p>
|
||
</dd></dl>
|
||
|
||
<p><a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 作为函数装饰器,为你创建 mock 并将其传入被装饰的函数:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'__main__.SomeClass'</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">function</span><span class="p">(</span><span class="n">normal_argument</span><span class="p">,</span> <span class="n">mock_class</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">mock_class</span> <span class="ow">is</span> <span class="n">SomeClass</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">function</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>为类打补丁将把该类替换为 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 的 <em>实例</em>。 如果该类是在受测试的代码中被实例化的则它将为所要使用的 mock 的 <a class="reference internal" href="#unittest.mock.Mock.return_value" title="unittest.mock.Mock.return_value"><code class="xref py py-attr docutils literal notranslate"><span class="pre">return_value</span></code></a>。</p>
|
||
<p>如果该类被多次实例化则你可以使用 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 来每次返回一个新 mock。 或者你也可以将 <em>return_value</em> 设为你希望的任何对象。</p>
|
||
<p>要在被打补丁的类的 <em>实例</em> 的方法上配置返回值你必须在 <code class="xref py py-attr docutils literal notranslate"><span class="pre">return_value</span></code> 操作。 例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">method</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">pass</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.Class'</span><span class="p">)</span> <span class="k">as</span> <span class="n">MockClass</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="n">instance</span> <span class="o">=</span> <span class="n">MockClass</span><span class="o">.</span><span class="n">return_value</span>
|
||
<span class="gp">... </span> <span class="n">instance</span><span class="o">.</span><span class="n">method</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="s1">'foo'</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">Class</span><span class="p">()</span> <span class="ow">is</span> <span class="n">instance</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">Class</span><span class="p">()</span><span class="o">.</span><span class="n">method</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'foo'</span>
|
||
<span class="gp">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果你使用 <em>spec</em> 或 <em>spec_set</em> 并且 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 替换的是 <em>class</em>,那么所创建的 mock 的返回值将具有同样的 spec。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Original</span> <span class="o">=</span> <span class="n">Class</span>
|
||
<span class="gp">>>> </span><span class="n">patcher</span> <span class="o">=</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.Class'</span><span class="p">,</span> <span class="n">spec</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">MockClass</span> <span class="o">=</span> <span class="n">patcher</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">instance</span> <span class="o">=</span> <span class="n">MockClass</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">instance</span><span class="p">,</span> <span class="n">Original</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">patcher</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><em>new_callable</em> 参数适用于当你想要使用其他类来替代所创建的 mock 默认的 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 的场合。 例如,如果你想要使用 <a class="reference internal" href="#unittest.mock.NonCallableMock" title="unittest.mock.NonCallableMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">NonCallableMock</span></code></a>:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">thing</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.thing'</span><span class="p">,</span> <span class="n">new_callable</span><span class="o">=</span><span class="n">NonCallableMock</span><span class="p">)</span> <span class="k">as</span> <span class="n">mock_thing</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">thing</span> <span class="ow">is</span> <span class="n">mock_thing</span>
|
||
<span class="gp">... </span> <span class="n">thing</span><span class="p">()</span>
|
||
<span class="gp">...</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">TypeError</span>: <span class="n">'NonCallableMock' object is not callable</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>另一个使用场景是用 <a class="reference internal" href="io.html#io.StringIO" title="io.StringIO"><code class="xref py py-class docutils literal notranslate"><span class="pre">io.StringIO</span></code></a> 实例来替换某个对象:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">io</span> <span class="kn">import</span> <span class="n">StringIO</span>
|
||
<span class="gp">>>> </span><span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">'Something'</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'sys.stdout'</span><span class="p">,</span> <span class="n">new_callable</span><span class="o">=</span><span class="n">StringIO</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">mock_stdout</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">foo</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">mock_stdout</span><span class="o">.</span><span class="n">getvalue</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'Something</span><span class="se">\n</span><span class="s1">'</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">test</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>当 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 为你创建 mock 时,通常你需要做的第一件事就是配置该 mock。 某些配置可以在对 patch 的调用中完成。 你在调用时传入的任何关键字参数都将被用来在所创建的 mock 上设置属性:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">patcher</span> <span class="o">=</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.thing'</span><span class="p">,</span> <span class="n">first</span><span class="o">=</span><span class="s1">'one'</span><span class="p">,</span> <span class="n">second</span><span class="o">=</span><span class="s1">'two'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock_thing</span> <span class="o">=</span> <span class="n">patcher</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock_thing</span><span class="o">.</span><span class="n">first</span>
|
||
<span class="go">'one'</span>
|
||
<span class="gp">>>> </span><span class="n">mock_thing</span><span class="o">.</span><span class="n">second</span>
|
||
<span class="go">'two'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>除了所创建的 mock 的属性上的属性,例如 <a class="reference internal" href="#unittest.mock.Mock.return_value" title="unittest.mock.Mock.return_value"><code class="xref py py-attr docutils literal notranslate"><span class="pre">return_value</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a>,还可以配置子 mock 的属性。 将这些属性直接作为关键字参数传入在语义上是无效的,但是仍然能够使用 <code class="docutils literal notranslate"><span class="pre">**</span></code> 将以这些属性为键的字典扩展至一个 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 调用中</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">config</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'method.return_value'</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s1">'other.side_effect'</span><span class="p">:</span> <span class="ne">KeyError</span><span class="p">}</span>
|
||
<span class="gp">>>> </span><span class="n">patcher</span> <span class="o">=</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.thing'</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock_thing</span> <span class="o">=</span> <span class="n">patcher</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock_thing</span><span class="o">.</span><span class="n">method</span><span class="p">()</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="n">mock_thing</span><span class="o">.</span><span class="n">other</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">KeyError</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在默认情况下,尝试给某个模块中并不存在的函数(或者某个类中的方法或属性)打补丁将会失败并引发 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a>:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'sys.non_existing_attribute'</span><span class="p">,</span> <span class="mi">42</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">sys</span><span class="o">.</span><span class="n">non_existing_attribute</span> <span class="o">==</span> <span class="mi">42</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">test</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">AttributeError</span>: <span class="n"><module 'sys' (built-in)> does not have the attribute 'non_existing'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>但在对 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 的调用中添加 <code class="docutils literal notranslate"><span class="pre">create=True</span></code> 将使之前示例的效果符合预期:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'sys.non_existing_attribute'</span><span class="p">,</span> <span class="mi">42</span><span class="p">,</span> <span class="n">create</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">mock_stdout</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">sys</span><span class="o">.</span><span class="n">non_existing_attribute</span> <span class="o">==</span> <span class="mi">42</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">test</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>如果目标为异步函数那么 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 现在将返回一个 <a class="reference internal" href="#unittest.mock.AsyncMock" title="unittest.mock.AsyncMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncMock</span></code></a>。</p>
|
||
</div>
|
||
</section>
|
||
<section id="patch-object">
|
||
<h3>patch.object<a class="headerlink" href="#patch-object" title="永久链接至标题">¶</a></h3>
|
||
<dl class="function">
|
||
<dt id="unittest.mock.patch.object">
|
||
<code class="sig-prename descclassname">patch.</code><code class="sig-name descname">object</code><span class="sig-paren">(</span><em class="sig-param">target</em>, <em class="sig-param">attribute</em>, <em class="sig-param">new=DEFAULT</em>, <em class="sig-param">spec=None</em>, <em class="sig-param">create=False</em>, <em class="sig-param">spec_set=None</em>, <em class="sig-param">autospec=None</em>, <em class="sig-param">new_callable=None</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.patch.object" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>用一个 mock 对象为对象 (<em>target</em>) 中指定名称的成员 (<em>attribute</em>) 打补丁。</p>
|
||
<p><a class="reference internal" href="#unittest.mock.patch.object" title="unittest.mock.patch.object"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.object()</span></code></a> 可以被用作装饰器、类装饰器或上下文管理器。 <em>new</em>, <em>spec</em>, <em>create</em>, <em>spec_set</em>, <em>autospec</em> 和 <em>new_callable</em> 等参数的含义与 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 的相同。 与 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 类似,<a class="reference internal" href="#unittest.mock.patch.object" title="unittest.mock.patch.object"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.object()</span></code></a> 接受任意关键字参数用于配置它所创建的 mock 对象。</p>
|
||
<p>当用作类装饰器时 <a class="reference internal" href="#unittest.mock.patch.object" title="unittest.mock.patch.object"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.object()</span></code></a> 将认可 <code class="docutils literal notranslate"><span class="pre">patch.TEST_PREFIX</span></code> 作为选择所要包装方法的标准。</p>
|
||
</dd></dl>
|
||
|
||
<p>你可以附带三个参数或两个参数来调用 <a class="reference internal" href="#unittest.mock.patch.object" title="unittest.mock.patch.object"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.object()</span></code></a>。 三个参数的形式将接受要打补丁的对象、属性的名称以及将要替换该属性的对象。</p>
|
||
<p>将附带两个参数的形式调用时你将省略替换对象,还会为你创建一个 mock 并作为附加参数传入被装饰的函数:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nd">@patch</span><span class="o">.</span><span class="n">object</span><span class="p">(</span><span class="n">SomeClass</span><span class="p">,</span> <span class="s1">'class_method'</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">mock_method</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">SomeClass</span><span class="o">.</span><span class="n">class_method</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="n">mock_method</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">test</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>传给 <a class="reference internal" href="#unittest.mock.patch.object" title="unittest.mock.patch.object"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.object()</span></code></a> 的 <em>spec</em>, <em>create</em> 和其他参数的含义与 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 的同名参数相同。</p>
|
||
</section>
|
||
<section id="patch-dict">
|
||
<h3>patch.dict<a class="headerlink" href="#patch-dict" title="永久链接至标题">¶</a></h3>
|
||
<dl class="function">
|
||
<dt id="unittest.mock.patch.dict">
|
||
<code class="sig-prename descclassname">patch.</code><code class="sig-name descname">dict</code><span class="sig-paren">(</span><em class="sig-param">in_dict</em>, <em class="sig-param">values=()</em>, <em class="sig-param">clear=False</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.patch.dict" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>为一个目录或目录类对象打补丁,并在测试之后将该目录恢复到其初始状态。</p>
|
||
<p><em>in_dict</em> 可以是一个字典或映射类容器。 如果它是一个映射则它必须至少支持获取、设置和删除条目以及对键执行迭代。</p>
|
||
<p><em>in_dict</em> 也可以是一个指定字典名称的字符串,然后将通过导入操作来获取该字典。</p>
|
||
<p><em>values</em> 可以是一个要在字典中设置的值的字典。 <em>values</em> 也可以是一个包含 <code class="docutils literal notranslate"><span class="pre">(key,</span> <span class="pre">value)</span></code> 对的可迭代对象。</p>
|
||
<p>如果 <em>clear</em> 为真值则该字典将在设置新值之前先被清空。</p>
|
||
<p><a class="reference internal" href="#unittest.mock.patch.dict" title="unittest.mock.patch.dict"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.dict()</span></code></a> 也可以附带任意关键字参数调用以设置字典中的值。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>现在当 <a class="reference internal" href="#unittest.mock.patch.dict" title="unittest.mock.patch.dict"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.dict()</span></code></a> 被用作上下文管理器时将返回被打补丁的字典。now returns the patched dictionary when used as a context manager.</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<p><a class="reference internal" href="#unittest.mock.patch.dict" title="unittest.mock.patch.dict"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.dict()</span></code></a> 可被用作上下文管理器、装饰器或类装饰器:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">foo</span> <span class="o">=</span> <span class="p">{}</span>
|
||
<span class="gp">>>> </span><span class="nd">@patch</span><span class="o">.</span><span class="n">dict</span><span class="p">(</span><span class="n">foo</span><span class="p">,</span> <span class="p">{</span><span class="s1">'newkey'</span><span class="p">:</span> <span class="s1">'newvalue'</span><span class="p">})</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">foo</span> <span class="o">==</span> <span class="p">{</span><span class="s1">'newkey'</span><span class="p">:</span> <span class="s1">'newvalue'</span><span class="p">}</span>
|
||
<span class="gp">>>> </span><span class="n">test</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">foo</span> <span class="o">==</span> <span class="p">{}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>当被用作类装饰器时 <a class="reference internal" href="#unittest.mock.patch.dict" title="unittest.mock.patch.dict"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.dict()</span></code></a> 将认可 <code class="docutils literal notranslate"><span class="pre">patch.TEST_PREFIX</span></code> (默认值为 <code class="docutils literal notranslate"><span class="pre">'test'</span></code>) 作为选择所在包装方法的标准:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">os</span>
|
||
<span class="gp">>>> </span><span class="kn">import</span> <span class="nn">unittest</span>
|
||
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">unittest.mock</span> <span class="kn">import</span> <span class="n">patch</span>
|
||
<span class="gp">>>> </span><span class="nd">@patch</span><span class="o">.</span><span class="n">dict</span><span class="p">(</span><span class="s1">'os.environ'</span><span class="p">,</span> <span class="p">{</span><span class="s1">'newkey'</span><span class="p">:</span> <span class="s1">'newvalue'</span><span class="p">})</span>
|
||
<span class="gp">... </span><span class="k">class</span> <span class="nc">TestSample</span><span class="p">(</span><span class="n">unittest</span><span class="o">.</span><span class="n">TestCase</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">test_sample</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s1">'newkey'</span><span class="p">],</span> <span class="s1">'newvalue'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果你在为你的测试使用不同的前缀,你可以通过设置 <code class="docutils literal notranslate"><span class="pre">patch.TEST_PREFIX</span></code> 来将不同的前缀告知打补丁方。 有关如何修改该值的详情请参阅 <a class="reference internal" href="#test-prefix"><span class="std std-ref">TEST_PREFIX</span></a>。</p>
|
||
<p><a class="reference internal" href="#unittest.mock.patch.dict" title="unittest.mock.patch.dict"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.dict()</span></code></a> 可被用来向一个字典添加成员,或者简单地让测试修改一个字典,并确保当测试结束时恢复该字典。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">foo</span> <span class="o">=</span> <span class="p">{}</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="o">.</span><span class="n">dict</span><span class="p">(</span><span class="n">foo</span><span class="p">,</span> <span class="p">{</span><span class="s1">'newkey'</span><span class="p">:</span> <span class="s1">'newvalue'</span><span class="p">})</span> <span class="k">as</span> <span class="n">patched_foo</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">foo</span> <span class="o">==</span> <span class="p">{</span><span class="s1">'newkey'</span><span class="p">:</span> <span class="s1">'newvalue'</span><span class="p">}</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">patched_foo</span> <span class="o">==</span> <span class="p">{</span><span class="s1">'newkey'</span><span class="p">:</span> <span class="s1">'newvalue'</span><span class="p">}</span>
|
||
<span class="gp">... </span> <span class="c1"># You can add, update or delete keys of foo (or patched_foo, it's the same dict)</span>
|
||
<span class="gp">... </span> <span class="n">patched_foo</span><span class="p">[</span><span class="s1">'spam'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'eggs'</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">foo</span> <span class="o">==</span> <span class="p">{}</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">patched_foo</span> <span class="o">==</span> <span class="p">{}</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">os</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="o">.</span><span class="n">dict</span><span class="p">(</span><span class="s1">'os.environ'</span><span class="p">,</span> <span class="p">{</span><span class="s1">'newkey'</span><span class="p">:</span> <span class="s1">'newvalue'</span><span class="p">}):</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s1">'newkey'</span><span class="p">])</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">newvalue</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="s1">'newkey'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>可以在 <a class="reference internal" href="#unittest.mock.patch.dict" title="unittest.mock.patch.dict"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.dict()</span></code></a> 调用中使用关键字来设置字典的值:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mymodule</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mymodule</span><span class="o">.</span><span class="n">function</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="s1">'fish'</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="o">.</span><span class="n">dict</span><span class="p">(</span><span class="s1">'sys.modules'</span><span class="p">,</span> <span class="n">mymodule</span><span class="o">=</span><span class="n">mymodule</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="kn">import</span> <span class="nn">mymodule</span>
|
||
<span class="gp">... </span> <span class="n">mymodule</span><span class="o">.</span><span class="n">function</span><span class="p">(</span><span class="s1">'some'</span><span class="p">,</span> <span class="s1">'args'</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">'fish'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.patch.dict" title="unittest.mock.patch.dict"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.dict()</span></code></a> 可以用于实际上不是字典的字典类对象。 它们最少必须支持条目获取、设置、删除以及迭代或成员检测两者中的一个。 这对应于魔术方法 <a class="reference internal" href="../reference/datamodel.html#object.__getitem__" title="object.__getitem__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__getitem__()</span></code></a>, <a class="reference internal" href="../reference/datamodel.html#object.__setitem__" title="object.__setitem__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__setitem__()</span></code></a>, <a class="reference internal" href="../reference/datamodel.html#object.__delitem__" title="object.__delitem__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__delitem__()</span></code></a> 以及 <a class="reference internal" href="../reference/datamodel.html#object.__iter__" title="object.__iter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__iter__()</span></code></a> 或 <a class="reference internal" href="../reference/datamodel.html#object.__contains__" title="object.__contains__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__contains__()</span></code></a>。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Container</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">values</span> <span class="o">=</span> <span class="p">{}</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">values</span><span class="p">[</span><span class="n">name</span><span class="p">]</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="fm">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">values</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="fm">__delitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">values</span><span class="p">[</span><span class="n">name</span><span class="p">]</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">values</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">thing</span> <span class="o">=</span> <span class="n">Container</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">thing</span><span class="p">[</span><span class="s1">'one'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="o">.</span><span class="n">dict</span><span class="p">(</span><span class="n">thing</span><span class="p">,</span> <span class="n">one</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">two</span><span class="o">=</span><span class="mi">3</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">thing</span><span class="p">[</span><span class="s1">'one'</span><span class="p">]</span> <span class="o">==</span> <span class="mi">2</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">thing</span><span class="p">[</span><span class="s1">'two'</span><span class="p">]</span> <span class="o">==</span> <span class="mi">3</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">thing</span><span class="p">[</span><span class="s1">'one'</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="nb">list</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span> <span class="o">==</span> <span class="p">[</span><span class="s1">'one'</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="patch-multiple">
|
||
<h3>patch.multiple<a class="headerlink" href="#patch-multiple" title="永久链接至标题">¶</a></h3>
|
||
<dl class="function">
|
||
<dt id="unittest.mock.patch.multiple">
|
||
<code class="sig-prename descclassname">patch.</code><code class="sig-name descname">multiple</code><span class="sig-paren">(</span><em class="sig-param">target</em>, <em class="sig-param">spec=None</em>, <em class="sig-param">create=False</em>, <em class="sig-param">spec_set=None</em>, <em class="sig-param">autospec=None</em>, <em class="sig-param">new_callable=None</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.patch.multiple" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>在单个调用中执行多重补丁。 它接受要打补丁的对象(一个对象或一个通过导入来获取对象的字符串)以及用于补丁的关键字参数:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">patch</span><span class="o">.</span><span class="n">multiple</span><span class="p">(</span><span class="n">settings</span><span class="p">,</span> <span class="n">FIRST_PATCH</span><span class="o">=</span><span class="s1">'one'</span><span class="p">,</span> <span class="n">SECOND_PATCH</span><span class="o">=</span><span class="s1">'two'</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果你希望 <a class="reference internal" href="#unittest.mock.patch.multiple" title="unittest.mock.patch.multiple"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.multiple()</span></code></a> 为你创建 mock 则要使用 <a class="reference internal" href="#unittest.mock.DEFAULT" title="unittest.mock.DEFAULT"><code class="xref py py-data docutils literal notranslate"><span class="pre">DEFAULT</span></code></a> 作为值。 在此情况下所创建的 mock 会通过关键字参数传入被装饰的函数,而当 <a class="reference internal" href="#unittest.mock.patch.multiple" title="unittest.mock.patch.multiple"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.multiple()</span></code></a> 被用作上下文管理器时则将返回一个字典。</p>
|
||
<p><a class="reference internal" href="#unittest.mock.patch.multiple" title="unittest.mock.patch.multiple"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.multiple()</span></code></a> 可以被用作装饰器、类装饰器或上下文管理器。 <em>spec</em>, <em>spec_set</em>, <em>create</em>, <em>autospec</em> 和 <em>new_callable</em> 等参数的含义与 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 的相同。 这些参数将被应用到 <a class="reference internal" href="#unittest.mock.patch.multiple" title="unittest.mock.patch.multiple"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.multiple()</span></code></a> 所打的 <em>所有</em> 补丁。</p>
|
||
<p>当被用作类装饰器时 <a class="reference internal" href="#unittest.mock.patch.multiple" title="unittest.mock.patch.multiple"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.multiple()</span></code></a> 将认可 <code class="docutils literal notranslate"><span class="pre">patch.TEST_PREFIX</span></code> 作为选择所要包装方法的标准。</p>
|
||
</dd></dl>
|
||
|
||
<p>如果你希望 <a class="reference internal" href="#unittest.mock.patch.multiple" title="unittest.mock.patch.multiple"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.multiple()</span></code></a> 为你创建 mock,那么你可以使用 <a class="reference internal" href="#unittest.mock.DEFAULT" title="unittest.mock.DEFAULT"><code class="xref py py-data docutils literal notranslate"><span class="pre">DEFAULT</span></code></a> 作为值。 如果你使用 <a class="reference internal" href="#unittest.mock.patch.multiple" title="unittest.mock.patch.multiple"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.multiple()</span></code></a> 作为装饰器则所创建的 mock 会作为关键字参数传入被装饰的函数。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">thing</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">other</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span>
|
||
|
||
<span class="gp">>>> </span><span class="nd">@patch</span><span class="o">.</span><span class="n">multiple</span><span class="p">(</span><span class="s1">'__main__'</span><span class="p">,</span> <span class="n">thing</span><span class="o">=</span><span class="n">DEFAULT</span><span class="p">,</span> <span class="n">other</span><span class="o">=</span><span class="n">DEFAULT</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">test_function</span><span class="p">(</span><span class="n">thing</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">thing</span><span class="p">,</span> <span class="n">MagicMock</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">MagicMock</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">test_function</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.patch.multiple" title="unittest.mock.patch.multiple"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.multiple()</span></code></a> 可以与其他 <code class="docutils literal notranslate"><span class="pre">patch</span></code> 装饰器嵌套使用,但要将作为关键字传入的参数要放在 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 所创建的标准参数 <em>之后</em>:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'sys.exit'</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="nd">@patch</span><span class="o">.</span><span class="n">multiple</span><span class="p">(</span><span class="s1">'__main__'</span><span class="p">,</span> <span class="n">thing</span><span class="o">=</span><span class="n">DEFAULT</span><span class="p">,</span> <span class="n">other</span><span class="o">=</span><span class="n">DEFAULT</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">test_function</span><span class="p">(</span><span class="n">mock_exit</span><span class="p">,</span> <span class="n">other</span><span class="p">,</span> <span class="n">thing</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="s1">'other'</span> <span class="ow">in</span> <span class="nb">repr</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="s1">'thing'</span> <span class="ow">in</span> <span class="nb">repr</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="s1">'exit'</span> <span class="ow">in</span> <span class="nb">repr</span><span class="p">(</span><span class="n">mock_exit</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">test_function</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果 <a class="reference internal" href="#unittest.mock.patch.multiple" title="unittest.mock.patch.multiple"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.multiple()</span></code></a> 被用作上下文管理器,则上下文管理器的返回值将是一个以所创建的 mock 的名称为键的字典:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="o">.</span><span class="n">multiple</span><span class="p">(</span><span class="s1">'__main__'</span><span class="p">,</span> <span class="n">thing</span><span class="o">=</span><span class="n">DEFAULT</span><span class="p">,</span> <span class="n">other</span><span class="o">=</span><span class="n">DEFAULT</span><span class="p">)</span> <span class="k">as</span> <span class="n">values</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="s1">'other'</span> <span class="ow">in</span> <span class="nb">repr</span><span class="p">(</span><span class="n">values</span><span class="p">[</span><span class="s1">'other'</span><span class="p">])</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="s1">'thing'</span> <span class="ow">in</span> <span class="nb">repr</span><span class="p">(</span><span class="n">values</span><span class="p">[</span><span class="s1">'thing'</span><span class="p">])</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">values</span><span class="p">[</span><span class="s1">'thing'</span><span class="p">]</span> <span class="ow">is</span> <span class="n">thing</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">values</span><span class="p">[</span><span class="s1">'other'</span><span class="p">]</span> <span class="ow">is</span> <span class="n">other</span>
|
||
<span class="gp">...</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="patch-methods-start-and-stop">
|
||
<span id="start-and-stop"></span><h3>补丁方法: start 和 stop<a class="headerlink" href="#patch-methods-start-and-stop" title="永久链接至标题">¶</a></h3>
|
||
<p>所有补丁对象都具有 <code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code> 和 <code class="xref py py-meth docutils literal notranslate"><span class="pre">stop()</span></code> 方法。 使用这些方法可以更简单地在 <code class="docutils literal notranslate"><span class="pre">setUp</span></code> 方法上打补丁,还可以让你不必嵌套使用装饰器或 with 语句就能打多重补丁。</p>
|
||
<p>要使用这些方法请按正常方式调用 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a>, <a class="reference internal" href="#unittest.mock.patch.object" title="unittest.mock.patch.object"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.object()</span></code></a> 或 <a class="reference internal" href="#unittest.mock.patch.dict" title="unittest.mock.patch.dict"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.dict()</span></code></a> 并保留一个指向所返回 <code class="docutils literal notranslate"><span class="pre">patcher</span></code> 对象的引用。 然后你可以调用 <code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code> 来原地打补丁并调用 <code class="xref py py-meth docutils literal notranslate"><span class="pre">stop()</span></code> 来恢复它。</p>
|
||
<p>如果你使用 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 来创建自己的 mock 那么将可通过调用 <code class="docutils literal notranslate"><span class="pre">patcher.start</span></code> 来返回它。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">patcher</span> <span class="o">=</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'package.module.ClassName'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">package</span> <span class="kn">import</span> <span class="n">module</span>
|
||
<span class="gp">>>> </span><span class="n">original</span> <span class="o">=</span> <span class="n">module</span><span class="o">.</span><span class="n">ClassName</span>
|
||
<span class="gp">>>> </span><span class="n">new_mock</span> <span class="o">=</span> <span class="n">patcher</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">module</span><span class="o">.</span><span class="n">ClassName</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">original</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">module</span><span class="o">.</span><span class="n">ClassName</span> <span class="ow">is</span> <span class="n">new_mock</span>
|
||
<span class="gp">>>> </span><span class="n">patcher</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">module</span><span class="o">.</span><span class="n">ClassName</span> <span class="ow">is</span> <span class="n">original</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">module</span><span class="o">.</span><span class="n">ClassName</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">new_mock</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>此操作的一个典型应用场景是在一个 <code class="xref py py-class docutils literal notranslate"><span class="pre">TestCase</span></code> 的 <code class="docutils literal notranslate"><span class="pre">setUp</span></code> 方法中执行多重补丁:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">MyTest</span><span class="p">(</span><span class="n">unittest</span><span class="o">.</span><span class="n">TestCase</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">setUp</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">patcher1</span> <span class="o">=</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'package.module.Class1'</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">patcher2</span> <span class="o">=</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'package.module.Class2'</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">MockClass1</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">patcher1</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">MockClass2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">patcher2</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">tearDown</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">patcher1</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">patcher2</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">test_something</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">package</span><span class="o">.</span><span class="n">module</span><span class="o">.</span><span class="n">Class1</span> <span class="ow">is</span> <span class="bp">self</span><span class="o">.</span><span class="n">MockClass1</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">package</span><span class="o">.</span><span class="n">module</span><span class="o">.</span><span class="n">Class2</span> <span class="ow">is</span> <span class="bp">self</span><span class="o">.</span><span class="n">MockClass2</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">MyTest</span><span class="p">(</span><span class="s1">'test_something'</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="admonition caution">
|
||
<p class="admonition-title">警告</p>
|
||
<p>如果你要使用这个技巧则你必须通过调用 <code class="docutils literal notranslate"><span class="pre">stop</span></code> 来确保补丁被“恢复”。 这可能要比你想像的更麻烦,因为如果在 <code class="docutils literal notranslate"><span class="pre">setUp</span></code> 中引发了异常那么 <code class="docutils literal notranslate"><span class="pre">tearDown</span></code> 将不会被调用。 <a class="reference internal" href="unittest.html#unittest.TestCase.addCleanup" title="unittest.TestCase.addCleanup"><code class="xref py py-meth docutils literal notranslate"><span class="pre">unittest.TestCase.addCleanup()</span></code></a> 可以简化此操作:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">MyTest</span><span class="p">(</span><span class="n">unittest</span><span class="o">.</span><span class="n">TestCase</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">setUp</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">patcher</span> <span class="o">=</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'package.module.Class'</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">MockClass</span> <span class="o">=</span> <span class="n">patcher</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">addCleanup</span><span class="p">(</span><span class="n">patcher</span><span class="o">.</span><span class="n">stop</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">test_something</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">package</span><span class="o">.</span><span class="n">module</span><span class="o">.</span><span class="n">Class</span> <span class="ow">is</span> <span class="bp">self</span><span class="o">.</span><span class="n">MockClass</span>
|
||
<span class="gp">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>一项额外的好处是你不再需要保留指向 <code class="docutils literal notranslate"><span class="pre">patcher</span></code> 对象的引用。</p>
|
||
</div>
|
||
<p>还可以通过使用 <a class="reference internal" href="#unittest.mock.patch.stopall" title="unittest.mock.patch.stopall"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.stopall()</span></code></a> 来停止已启动的所有补丁。</p>
|
||
<dl class="function">
|
||
<dt id="unittest.mock.patch.stopall">
|
||
<code class="sig-prename descclassname">patch.</code><code class="sig-name descname">stopall</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.patch.stopall" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>停止所有激活的补丁。 仅会停止通过 <code class="docutils literal notranslate"><span class="pre">start</span></code> 启动的补丁。</p>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="patch-builtins">
|
||
<span id="id4"></span><h3>为内置对象打补丁<a class="headerlink" href="#patch-builtins" title="永久链接至标题">¶</a></h3>
|
||
<p>你可以为一个模块中的任何内置函数打补丁。 以以示例是为内置函数 <a class="reference internal" href="functions.html#ord" title="ord"><code class="xref py py-func docutils literal notranslate"><span class="pre">ord()</span></code></a> 打补丁:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'__main__.ord'</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">mock_ord</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">mock_ord</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="mi">101</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="s1">'c'</span><span class="p">))</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">test</span><span class="p">()</span>
|
||
<span class="go">101</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="test-prefix">
|
||
<span id="id5"></span><h3>TEST_PREFIX<a class="headerlink" href="#test-prefix" title="永久链接至标题">¶</a></h3>
|
||
<p>所有补丁都可被用作类装饰器。 当以这种方式使用时它们将会包装类中的每个测试方法。 补丁会将以名字以 <code class="docutils literal notranslate"><span class="pre">'test'</span></code> 开头的方法识别为测试方法。 这与 <a class="reference internal" href="unittest.html#unittest.TestLoader" title="unittest.TestLoader"><code class="xref py py-class docutils literal notranslate"><span class="pre">unittest.TestLoader</span></code></a> 查找测试方法的默认方式相同。</p>
|
||
<p>你可能会想要为你的测试使用不同的前缀。 你可以通过设置 <code class="docutils literal notranslate"><span class="pre">patch.TEST_PREFIX</span></code> 来告知打补丁方不同的前缀:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">patch</span><span class="o">.</span><span class="n">TEST_PREFIX</span> <span class="o">=</span> <span class="s1">'foo'</span>
|
||
<span class="gp">>>> </span><span class="n">value</span> <span class="o">=</span> <span class="mi">3</span>
|
||
<span class="gp">>>></span>
|
||
<span class="gp">>>> </span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'__main__.value'</span><span class="p">,</span> <span class="s1">'not three'</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">class</span> <span class="nc">Thing</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">foo_one</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">foo_two</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>></span>
|
||
<span class="gp">>>> </span><span class="n">Thing</span><span class="p">()</span><span class="o">.</span><span class="n">foo_one</span><span class="p">()</span>
|
||
<span class="go">not three</span>
|
||
<span class="gp">>>> </span><span class="n">Thing</span><span class="p">()</span><span class="o">.</span><span class="n">foo_two</span><span class="p">()</span>
|
||
<span class="go">not three</span>
|
||
<span class="gp">>>> </span><span class="n">value</span>
|
||
<span class="go">3</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="nesting-patch-decorators">
|
||
<h3>嵌套补丁装饰器<a class="headerlink" href="#nesting-patch-decorators" title="永久链接至标题">¶</a></h3>
|
||
<p>如果你想要应用多重补丁那么你可以简单地堆叠多个装饰器。</p>
|
||
<p>你可以使用以下模式来堆叠多个补丁装饰器:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nd">@patch</span><span class="o">.</span><span class="n">object</span><span class="p">(</span><span class="n">SomeClass</span><span class="p">,</span> <span class="s1">'class_method'</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="nd">@patch</span><span class="o">.</span><span class="n">object</span><span class="p">(</span><span class="n">SomeClass</span><span class="p">,</span> <span class="s1">'static_method'</span><span class="p">)</span>
|
||
<span class="gp">... </span><span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">mock1</span><span class="p">,</span> <span class="n">mock2</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">SomeClass</span><span class="o">.</span><span class="n">static_method</span> <span class="ow">is</span> <span class="n">mock1</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">SomeClass</span><span class="o">.</span><span class="n">class_method</span> <span class="ow">is</span> <span class="n">mock2</span>
|
||
<span class="gp">... </span> <span class="n">SomeClass</span><span class="o">.</span><span class="n">static_method</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="n">SomeClass</span><span class="o">.</span><span class="n">class_method</span><span class="p">(</span><span class="s1">'bar'</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">mock1</span><span class="p">,</span> <span class="n">mock2</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock1</span><span class="p">,</span> <span class="n">mock2</span> <span class="o">=</span> <span class="n">test</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock1</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock2</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="s1">'bar'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>请注意装饰器是从下往上被应用的。 这是 Python 应用装饰器的标准方式。 被创建并传入你的测试函数的 mock 的顺序也将匹配这个顺序。</p>
|
||
</section>
|
||
<section id="where-to-patch">
|
||
<span id="id6"></span><h3>补丁的目标<a class="headerlink" href="#where-to-patch" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 通过(临时性地)修改某一个对象的 <em>名称</em> 指向另一个对象来发挥作用。 可以有多个名称指向任意单独对象,因此要让补丁起作用你必须确保已为被测试的系统所使用的名称打上补丁。</p>
|
||
<p>基本原则是你要在对象 <em>被查找</em> 的地方打补丁,这不一定就是它被定义的地方。 一组示例将有助于厘清这一点。</p>
|
||
<p>想像我们有一个想要测试的具有如下结构的项目:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">a</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="o">-></span> <span class="n">Defines</span> <span class="n">SomeClass</span>
|
||
|
||
<span class="n">b</span><span class="o">.</span><span class="n">py</span>
|
||
<span class="o">-></span> <span class="kn">from</span> <span class="nn">a</span> <span class="kn">import</span> <span class="n">SomeClass</span>
|
||
<span class="o">-></span> <span class="n">some_function</span> <span class="n">instantiates</span> <span class="n">SomeClass</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>现在我们要测试 <code class="docutils literal notranslate"><span class="pre">some_function</span></code> 但我们想使用 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 来模拟 <code class="docutils literal notranslate"><span class="pre">SomeClass</span></code>。 问题在于当我们导入模块 b 时,我们将必须让它从模块 a 导入 <code class="docutils literal notranslate"><span class="pre">SomeClass</span></code>。 如果我们使用 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 来模拟 <code class="docutils literal notranslate"><span class="pre">a.SomeClass</span></code> 那么它将不会对我们的测试造成影响;模块 b 已经拥有对 <em>真正的</em> <code class="docutils literal notranslate"><span class="pre">SomeClass</span></code> 的引用因此看上去我们的补丁不会有任何影响。</p>
|
||
<p>关键在于对 <code class="docutils literal notranslate"><span class="pre">SomeClass</span></code> 打补丁操作是在它被使用(或它被查找)的地方。 在此情况下实际上 <code class="docutils literal notranslate"><span class="pre">some_function</span></code> 将在模块 b 中查找 <code class="docutils literal notranslate"><span class="pre">SomeClass</span></code>,而我们已经在那里导入了它。 补丁看上去应该是这样:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'b.SomeClass'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>但是,再考虑另一个场景,其中不是 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">a</span> <span class="pre">import</span> <span class="pre">SomeClass</span></code> 而是模块 b 执行了 <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">a</span></code> 并且 <code class="docutils literal notranslate"><span class="pre">some_function</span></code> 使用了 <code class="docutils literal notranslate"><span class="pre">a.SomeClass</span></code>。 这两个导入形式都很常见。 在这种情况下我们要打补丁的类将在该模块中被查找因而我们必须改为对 <code class="docutils literal notranslate"><span class="pre">a.SomeClass</span></code> 打补丁:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@patch</span><span class="p">(</span><span class="s1">'a.SomeClass'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="patching-descriptors-and-proxy-objects">
|
||
<h3>对描述器和代理对象打补丁<a class="headerlink" href="#patching-descriptors-and-proxy-objects" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="#patch">patch</a> 和 <a class="reference internal" href="#patch-object">patch.object</a> 都能正确地对描述器打补丁并恢复:包括类方法、静态方法和特征属性。 你应当在 <em>类</em> 而不是在实例上为它们打补丁。 它们还适用于代理属性访问的 <em>某些</em> 对象,例如 <a class="reference external" href="http://www.voidspace.org.uk/python/weblog/arch_d7_2010_12_04.shtml#e1198">django 设置对象</a>。</p>
|
||
</section>
|
||
</section>
|
||
<section id="magicmock-and-magic-method-support">
|
||
<h2>MagicMock 与魔术方法支持<a class="headerlink" href="#magicmock-and-magic-method-support" title="永久链接至标题">¶</a></h2>
|
||
<section id="mocking-magic-methods">
|
||
<span id="magic-methods"></span><h3>模拟魔术方法<a class="headerlink" href="#mocking-magic-methods" title="永久链接至标题">¶</a></h3>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 支持模拟 Python 协议方法,或称“魔术方法”。 这允许 mock 对象替代容器或其他实现了 Python 协议的对象。</p>
|
||
<p>因为查找魔术方法的方式不同于普通方法 <a class="footnote-reference brackets" href="#id9" id="id7">2</a>,这种支持采用了特别的实现。 这意味着只有特定的魔术方法受到支持。 受支持的是 <em>几乎</em> 所有魔术方法。 如果有你需要但被遗漏的请告知我们。</p>
|
||
<p>你可以通过在某个函数或 mock 实例中设置魔术方法来模拟它们。 如果你是使用函数则它 <em>必须</em> 接受 <code class="docutils literal notranslate"><span class="pre">self</span></code> 作为第一个参数 <a class="footnote-reference brackets" href="#id10" id="id8">3</a>。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="s1">'fooble'</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__str__</span> <span class="o">=</span> <span class="fm">__str__</span>
|
||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">'fooble'</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__str__</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__str__</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="s1">'fooble'</span>
|
||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">'fooble'</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__iter__</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="nb">iter</span><span class="p">([]))</span>
|
||
<span class="gp">>>> </span><span class="nb">list</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">[]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>一个这样的应用场景是在 <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> 语句中模拟作为上下文管理器的对象:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__enter__</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="s1">'foo'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__exit__</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">mock</span> <span class="k">as</span> <span class="n">m</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">assert</span> <span class="n">m</span> <span class="o">==</span> <span class="s1">'foo'</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__enter__</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__exit__</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>对魔术方法的调用不会在 <a class="reference internal" href="#unittest.mock.Mock.method_calls" title="unittest.mock.Mock.method_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">method_calls</span></code></a> 中出现,但它们会被记录在 <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 中。</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">注解</p>
|
||
<p>如果你使用 <em>spec</em> 关键字参数来创建 mock 那么尝试设置不包含在 spec 中的魔术方法将引发 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a>。</p>
|
||
</div>
|
||
<p>受支持魔术方法的完整列表如下:</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__hash__</span></code>, <code class="docutils literal notranslate"><span class="pre">__sizeof__</span></code>, <code class="docutils literal notranslate"><span class="pre">__repr__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__str__</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__dir__</span></code>, <code class="docutils literal notranslate"><span class="pre">__format__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__subclasses__</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__round__</span></code>, <code class="docutils literal notranslate"><span class="pre">__floor__</span></code>, <code class="docutils literal notranslate"><span class="pre">__trunc__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__ceil__</span></code></p></li>
|
||
<li><p>比较运算: <code class="docutils literal notranslate"><span class="pre">__lt__</span></code>, <code class="docutils literal notranslate"><span class="pre">__gt__</span></code>, <code class="docutils literal notranslate"><span class="pre">__le__</span></code>, <code class="docutils literal notranslate"><span class="pre">__ge__</span></code>, <code class="docutils literal notranslate"><span class="pre">__eq__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__ne__</span></code></p></li>
|
||
<li><p>容器方法: <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code>, <code class="docutils literal notranslate"><span class="pre">__setitem__</span></code>, <code class="docutils literal notranslate"><span class="pre">__delitem__</span></code>, <code class="docutils literal notranslate"><span class="pre">__contains__</span></code>, <code class="docutils literal notranslate"><span class="pre">__len__</span></code>, <code class="docutils literal notranslate"><span class="pre">__iter__</span></code>, <code class="docutils literal notranslate"><span class="pre">__reversed__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__missing__</span></code></p></li>
|
||
<li><p>上下文管理器: <code class="docutils literal notranslate"><span class="pre">__enter__</span></code>, <code class="docutils literal notranslate"><span class="pre">__exit__</span></code>, <code class="docutils literal notranslate"><span class="pre">__aenter__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__aexit__</span></code></p></li>
|
||
<li><p>单目数值运算方法: <code class="docutils literal notranslate"><span class="pre">__neg__</span></code>, <code class="docutils literal notranslate"><span class="pre">__pos__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__invert__</span></code></p></li>
|
||
<li><p>数值运算方法 (包括右手和原地形式): <code class="docutils literal notranslate"><span class="pre">__add__</span></code>, <code class="docutils literal notranslate"><span class="pre">__sub__</span></code>, <code class="docutils literal notranslate"><span class="pre">__mul__</span></code>, <code class="docutils literal notranslate"><span class="pre">__matmul__</span></code>, <code class="docutils literal notranslate"><span class="pre">__div__</span></code>, <code class="docutils literal notranslate"><span class="pre">__truediv__</span></code>, <code class="docutils literal notranslate"><span class="pre">__floordiv__</span></code>, <code class="docutils literal notranslate"><span class="pre">__mod__</span></code>, <code class="docutils literal notranslate"><span class="pre">__divmod__</span></code>, <code class="docutils literal notranslate"><span class="pre">__lshift__</span></code>, <code class="docutils literal notranslate"><span class="pre">__rshift__</span></code>, <code class="docutils literal notranslate"><span class="pre">__and__</span></code>, <code class="docutils literal notranslate"><span class="pre">__xor__</span></code>, <code class="docutils literal notranslate"><span class="pre">__or__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__pow__</span></code></p></li>
|
||
<li><p>数值转换方法: <code class="docutils literal notranslate"><span class="pre">__complex__</span></code>, <code class="docutils literal notranslate"><span class="pre">__int__</span></code>, <code class="docutils literal notranslate"><span class="pre">__float__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__index__</span></code></p></li>
|
||
<li><p>描述器方法: <code class="docutils literal notranslate"><span class="pre">__get__</span></code>, <code class="docutils literal notranslate"><span class="pre">__set__</span></code> and <code class="docutils literal notranslate"><span class="pre">__delete__</span></code></p></li>
|
||
<li><p>封存方法: <code class="docutils literal notranslate"><span class="pre">__reduce__</span></code>, <code class="docutils literal notranslate"><span class="pre">__reduce_ex__</span></code>, <code class="docutils literal notranslate"><span class="pre">__getinitargs__</span></code>, <code class="docutils literal notranslate"><span class="pre">__getnewargs__</span></code>, <code class="docutils literal notranslate"><span class="pre">__getstate__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__setstate__</span></code></p></li>
|
||
<li><p>文件系统路径表示: <code class="docutils literal notranslate"><span class="pre">__fspath__</span></code></p></li>
|
||
<li><p>异步迭代方法: <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> and <code class="docutils literal notranslate"><span class="pre">__anext__</span></code></p></li>
|
||
</ul>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>增加了对 <a class="reference internal" href="os.html#os.PathLike.__fspath__" title="os.PathLike.__fspath__"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.PathLike.__fspath__()</span></code></a> 的支持。</p>
|
||
</div>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>增加了对 <code class="docutils literal notranslate"><span class="pre">__aenter__</span></code>, <code class="docutils literal notranslate"><span class="pre">__aexit__</span></code>, <code class="docutils literal notranslate"><span class="pre">__aiter__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__anext__</span></code> 的支持。</p>
|
||
</div>
|
||
<p>下列方法均存在但是 <em>不受</em> 支持,因为它们或者被 mock 所使用,或者无法动态设置,或者可能导致问题:</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__getattr__</span></code>, <code class="docutils literal notranslate"><span class="pre">__setattr__</span></code>, <code class="docutils literal notranslate"><span class="pre">__init__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__new__</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__prepare__</span></code>, <code class="docutils literal notranslate"><span class="pre">__instancecheck__</span></code>, <code class="docutils literal notranslate"><span class="pre">__subclasscheck__</span></code>, <code class="docutils literal notranslate"><span class="pre">__del__</span></code></p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="magic-mock">
|
||
<h3>MagicMock<a class="headerlink" href="#magic-mock" title="永久链接至标题">¶</a></h3>
|
||
<p>存在两个版本的 <code class="docutils literal notranslate"><span class="pre">MagicMock</span></code>: <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 和 <a class="reference internal" href="#unittest.mock.NonCallableMagicMock" title="unittest.mock.NonCallableMagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">NonCallableMagicMock</span></code></a>.</p>
|
||
<dl class="class">
|
||
<dt id="unittest.mock.MagicMock">
|
||
<em class="property">class </em><code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">MagicMock</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kw</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.MagicMock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><code class="docutils literal notranslate"><span class="pre">MagicMock</span></code> 是包含了大部分魔术方法的默认实现的 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 的子类。 你可以使用 <code class="docutils literal notranslate"><span class="pre">MagicMock</span></code> 而无须自行配置魔术方法。without having to configure the magic methods yourself.</p>
|
||
<p>构造器形参的含义与 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 的相同。</p>
|
||
<p>如果你使用了 <em>spec</em> 或 <em>spec_set</em> 参数则将 <em>只有</em> 存在于 spec 中的魔术方法会被创建。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="unittest.mock.NonCallableMagicMock">
|
||
<em class="property">class </em><code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">NonCallableMagicMock</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kw</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.NonCallableMagicMock" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 的不可调用对象版本。</p>
|
||
<p>其构造器的形参具有与 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 相同的含义,区别在于 <em>return_value</em> 和 <em>side_effect</em> 在不可调用的 mock 上没有意义。</p>
|
||
</dd></dl>
|
||
|
||
<p>魔术方法是通过 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 对象来设置的,因此你可以用通常的方式来配置它们并使用它们:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'fish'</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__setitem__</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="s1">'fish'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__getitem__</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="s1">'result'</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||
<span class="go">'result'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在默认情况下许多协议方法都需要返回特定类型的对象。 这些方法都预先配置了默认的返回值,以便它们在你对返回值不感兴趣时可以不做任何事就能被使用。 如果你想要修改默认值则你仍然可以手动 <em>设置</em> 返回值。</p>
|
||
<p>方法及其默认返回值:</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__lt__</span></code>: <code class="docutils literal notranslate"><span class="pre">NotImplemented</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__gt__</span></code>: <code class="docutils literal notranslate"><span class="pre">NotImplemented</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__le__</span></code>: <code class="docutils literal notranslate"><span class="pre">NotImplemented</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__ge__</span></code>: <code class="docutils literal notranslate"><span class="pre">NotImplemented</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__int__</span></code>: <code class="docutils literal notranslate"><span class="pre">1</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__contains__</span></code>: <code class="docutils literal notranslate"><span class="pre">False</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__len__</span></code>: <code class="docutils literal notranslate"><span class="pre">0</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__iter__</span></code>: <code class="docutils literal notranslate"><span class="pre">iter([])</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__exit__</span></code>: <code class="docutils literal notranslate"><span class="pre">False</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__aexit__</span></code>: <code class="docutils literal notranslate"><span class="pre">False</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__complex__</span></code>: <code class="docutils literal notranslate"><span class="pre">1j</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__float__</span></code>: <code class="docutils literal notranslate"><span class="pre">1.0</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__bool__</span></code>: <code class="docutils literal notranslate"><span class="pre">True</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__index__</span></code>: <code class="docutils literal notranslate"><span class="pre">1</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__hash__</span></code>: mock 的默认 hash</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__str__</span></code>: mock 的默认 str</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__sizeof__</span></code>: mock 的默认 sizeof</p></li>
|
||
</ul>
|
||
<p>例如:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="nb">int</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">1</span>
|
||
<span class="gp">>>> </span><span class="nb">len</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">0</span>
|
||
<span class="gp">>>> </span><span class="nb">list</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">[]</span>
|
||
<span class="gp">>>> </span><span class="nb">object</span><span class="p">()</span> <span class="ow">in</span> <span class="n">mock</span>
|
||
<span class="go">False</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>两个相等性方法 <a class="reference internal" href="../reference/datamodel.html#object.__eq__" title="object.__eq__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__eq__()</span></code></a> 和 <a class="reference internal" href="../reference/datamodel.html#object.__ne__" title="object.__ne__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__ne__()</span></code></a> 是特殊的。 它们基于标识号进行默认的相等性比较,使用 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 属性,除非你修改它们的返回值以返回其他内容:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">MagicMock</span><span class="p">()</span> <span class="o">==</span> <span class="mi">3</span>
|
||
<span class="go">False</span>
|
||
<span class="gp">>>> </span><span class="n">MagicMock</span><span class="p">()</span> <span class="o">!=</span> <span class="mi">3</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__eq__</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="kc">True</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">==</span> <span class="mi">3</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="xref py py-meth docutils literal notranslate"><span class="pre">MagicMock.__iter__()</span></code> 的返回值可以是任意可迭代对象而不要求必须是迭代器:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__iter__</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'a'</span><span class="p">,</span> <span class="s1">'b'</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">]</span>
|
||
<span class="gp">>>> </span><span class="nb">list</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">['a', 'b', 'c']</span>
|
||
<span class="gp">>>> </span><span class="nb">list</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">['a', 'b', 'c']</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果返回值 <em>是</em> 迭代器,则对其执行一次迭代就会将它耗尽因而后续执行的迭代将会输出空列表:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="fm">__iter__</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">([</span><span class="s1">'a'</span><span class="p">,</span> <span class="s1">'b'</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">])</span>
|
||
<span class="gp">>>> </span><span class="nb">list</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">['a', 'b', 'c']</span>
|
||
<span class="gp">>>> </span><span class="nb">list</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="go">[]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="docutils literal notranslate"><span class="pre">MagicMock</span></code> 已配置了所有受支持的魔术方法,只有某些晦涩和过时的魔术方法是例外。 如果你需要仍然可以设置它们。</p>
|
||
<p>在 <code class="docutils literal notranslate"><span class="pre">MagicMock</span></code> 中受到支持但默认未被设置的魔术方法有:</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__subclasses__</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__dir__</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__format__</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__get__</span></code>, <code class="docutils literal notranslate"><span class="pre">__set__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__delete__</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__reversed__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__missing__</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__reduce__</span></code>, <code class="docutils literal notranslate"><span class="pre">__reduce_ex__</span></code>, <code class="docutils literal notranslate"><span class="pre">__getinitargs__</span></code>, <code class="docutils literal notranslate"><span class="pre">__getnewargs__</span></code>, <code class="docutils literal notranslate"><span class="pre">__getstate__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__setstate__</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">__getformat__</span></code> 和 <code class="docutils literal notranslate"><span class="pre">__setformat__</span></code></p></li>
|
||
</ul>
|
||
<dl class="footnote brackets">
|
||
<dt class="label" id="id9"><span class="brackets"><a class="fn-backref" href="#id7">2</a></span></dt>
|
||
<dd><p>魔术方法 <em>应当</em> 是在类中而不是在实例中查找。 不同的 Python 版本对这个规则的应用并不一致。 受支持的协议方法应当适用于所有受支持的 Python 版本。</p>
|
||
</dd>
|
||
<dt class="label" id="id10"><span class="brackets"><a class="fn-backref" href="#id8">3</a></span></dt>
|
||
<dd><p>该函数基本上是与类挂钩的,但每个 <code class="docutils literal notranslate"><span class="pre">Mock</span></code> 实例都会与其他实例保持隔离。</p>
|
||
</dd>
|
||
</dl>
|
||
</section>
|
||
</section>
|
||
<section id="helpers">
|
||
<h2>辅助对象<a class="headerlink" href="#helpers" title="永久链接至标题">¶</a></h2>
|
||
<section id="sentinel">
|
||
<h3>sentinel<a class="headerlink" href="#sentinel" title="永久链接至标题">¶</a></h3>
|
||
<dl class="data">
|
||
<dt id="unittest.mock.sentinel">
|
||
<code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">sentinel</code><a class="headerlink" href="#unittest.mock.sentinel" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><code class="docutils literal notranslate"><span class="pre">sentinel</span></code> 对象提供了一种为你的测试提供独特对象的便捷方式。</p>
|
||
<p>属性是在你通过名称访问它们时按需创建的。 访问相同的属性将始终返回相同的对象。 返回的对象会有一个合理的 repr 以使测试失败消息易于理解。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.7 版更改: </span>现在 <code class="docutils literal notranslate"><span class="pre">sentinel</span></code> 属性会在它们被 <a class="reference internal" href="copy.html#module-copy" title="copy: Shallow and deep copy operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">copy</span></code></a> 或 <a class="reference internal" href="pickle.html#module-pickle" title="pickle: Convert Python objects to streams of bytes and back."><code class="xref py py-mod docutils literal notranslate"><span class="pre">pickle</span></code></a> 时保存其标识。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<p>在测试时你可能需要测试是否有一个特定的对象作为参数被传给了另一个方法,或是被其返回。 通常的做法是创建一个指定名称的 sentinel 对象来执行这种测试。 <a class="reference internal" href="#unittest.mock.sentinel" title="unittest.mock.sentinel"><code class="xref py py-data docutils literal notranslate"><span class="pre">sentinel</span></code></a> 提供了一种创建和测试此类对象的标识的便捷方式。</p>
|
||
<p>在这个示例中我们为 <code class="docutils literal notranslate"><span class="pre">method</span></code> 打上便捷补丁以返回 <code class="docutils literal notranslate"><span class="pre">sentinel.some_object</span></code>:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">real</span> <span class="o">=</span> <span class="n">ProductionClass</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">real</span><span class="o">.</span><span class="n">method</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">"method"</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">real</span><span class="o">.</span><span class="n">method</span><span class="o">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="n">sentinel</span><span class="o">.</span><span class="n">some_object</span>
|
||
<span class="gp">>>> </span><span class="n">result</span> <span class="o">=</span> <span class="n">real</span><span class="o">.</span><span class="n">method</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">result</span> <span class="ow">is</span> <span class="n">sentinel</span><span class="o">.</span><span class="n">some_object</span>
|
||
<span class="gp">>>> </span><span class="n">sentinel</span><span class="o">.</span><span class="n">some_object</span>
|
||
<span class="go">sentinel.some_object</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="default">
|
||
<h3>DEFAULT<a class="headerlink" href="#default" title="永久链接至标题">¶</a></h3>
|
||
<dl class="data">
|
||
<dt id="unittest.mock.DEFAULT">
|
||
<code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">DEFAULT</code><a class="headerlink" href="#unittest.mock.DEFAULT" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#unittest.mock.DEFAULT" title="unittest.mock.DEFAULT"><code class="xref py py-data docutils literal notranslate"><span class="pre">DEFAULT</span></code></a> 对象是一个预先创建的 sentinel (实际为 <code class="docutils literal notranslate"><span class="pre">sentinel.DEFAULT</span></code>)。 它可被 <a class="reference internal" href="#unittest.mock.Mock.side_effect" title="unittest.mock.Mock.side_effect"><code class="xref py py-attr docutils literal notranslate"><span class="pre">side_effect</span></code></a> 函数用来指明其应当使用正常的返回值。</p>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="call">
|
||
<h3>call<a class="headerlink" href="#call" title="永久链接至标题">¶</a></h3>
|
||
<dl class="function">
|
||
<dt id="unittest.mock.call">
|
||
<code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">call</code><span class="sig-paren">(</span><em class="sig-param">*args</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.call" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#unittest.mock.call" title="unittest.mock.call"><code class="xref py py-func docutils literal notranslate"><span class="pre">call()</span></code></a> 是一个可创建更简单断言的辅助对象,用于同 <a class="reference internal" href="#unittest.mock.Mock.call_args" title="unittest.mock.Mock.call_args"><code class="xref py py-attr docutils literal notranslate"><span class="pre">call_args</span></code></a>, <a class="reference internal" href="#unittest.mock.Mock.call_args_list" title="unittest.mock.Mock.call_args_list"><code class="xref py py-attr docutils literal notranslate"><span class="pre">call_args_list</span></code></a>, <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.method_calls" title="unittest.mock.Mock.method_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">method_calls</span></code></a> 进行比较。 <a class="reference internal" href="#unittest.mock.call" title="unittest.mock.call"><code class="xref py py-func docutils literal notranslate"><span class="pre">call()</span></code></a> 也可配合 <a class="reference internal" href="#unittest.mock.Mock.assert_has_calls" title="unittest.mock.Mock.assert_has_calls"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_has_calls()</span></code></a> 使用。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">a</span><span class="o">=</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">call_args_list</span> <span class="o">==</span> <span class="p">[</span><span class="n">call</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">a</span><span class="o">=</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="s1">'bar'</span><span class="p">),</span> <span class="n">call</span><span class="p">()]</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="unittest.mock.call.call_list">
|
||
<code class="sig-prename descclassname">call.</code><code class="sig-name descname">call_list</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.call.call_list" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>对于代表多个调用的 call 对象,<a class="reference internal" href="#unittest.mock.call.call_list" title="unittest.mock.call.call_list"><code class="xref py py-meth docutils literal notranslate"><span class="pre">call_list()</span></code></a> 将返回一个包含所有中间调用以及最终调用的列表。</p>
|
||
</dd></dl>
|
||
|
||
<p><code class="docutils literal notranslate"><span class="pre">call_list</span></code> 特别适用于创建针对“链式调用”的断言。 链式调用是指在一行代码中执行的多个调用。 这将使得一个 mock 的中存在多个条目 <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a>。 手动构造调用的序列将会很烦琐。</p>
|
||
<p><a class="reference internal" href="#unittest.mock.call.call_list" title="unittest.mock.call.call_list"><code class="xref py py-meth docutils literal notranslate"><span class="pre">call_list()</span></code></a> 可以根据同一个链式调用构造包含多个调用的序列:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">method</span><span class="p">(</span><span class="n">arg</span><span class="o">=</span><span class="s1">'foo'</span><span class="p">)</span><span class="o">.</span><span class="n">other</span><span class="p">(</span><span class="s1">'bar'</span><span class="p">)(</span><span class="mf">2.0</span><span class="p">)</span>
|
||
<span class="go"><MagicMock name='mock().method().other()()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">kall</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">method</span><span class="p">(</span><span class="n">arg</span><span class="o">=</span><span class="s1">'foo'</span><span class="p">)</span><span class="o">.</span><span class="n">other</span><span class="p">(</span><span class="s1">'bar'</span><span class="p">)(</span><span class="mf">2.0</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">kall</span><span class="o">.</span><span class="n">call_list</span><span class="p">()</span>
|
||
<span class="go">[call(1),</span>
|
||
<span class="go"> call().method(arg='foo'),</span>
|
||
<span class="go"> call().method().other('bar'),</span>
|
||
<span class="go"> call().method().other()(2.0)]</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">mock_calls</span> <span class="o">==</span> <span class="n">kall</span><span class="o">.</span><span class="n">call_list</span><span class="p">()</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<p id="calls-as-tuples">根据构造方式的不同,<code class="docutils literal notranslate"><span class="pre">call</span></code> 对象可以是一个 (位置参数, 关键字参数) 或 (名称, 位置参数, 关键字参数) 元组。 当你自行构造它们时这没有什么关系,但是 <a class="reference internal" href="#unittest.mock.Mock.call_args" title="unittest.mock.Mock.call_args"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Mock.call_args</span></code></a>, <a class="reference internal" href="#unittest.mock.Mock.call_args_list" title="unittest.mock.Mock.call_args_list"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Mock.call_args_list</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Mock.mock_calls</span></code></a> 属性当中的 <code class="docutils literal notranslate"><span class="pre">call</span></code> 对象可以被反查以获取它们所包含的单个参数。</p>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock.call_args" title="unittest.mock.Mock.call_args"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Mock.call_args</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.call_args_list" title="unittest.mock.Mock.call_args_list"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Mock.call_args_list</span></code></a> 中的 <code class="docutils literal notranslate"><span class="pre">call</span></code> 对象是 (位置参数, 关键字参数) 二元组而 <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Mock.mock_calls</span></code></a> 中以及你自行构造的 <code class="docutils literal notranslate"><span class="pre">call</span></code> 对象则是 (名称, 位置参数, 关键字参数) 三元组。</p>
|
||
<p>你可以使用它们作为“元组”的特性来为更复杂的内省和断言功能获取单个参数。 位置参数是一个元组(如无位置参数则为空元组)而关键字参数是一个字典:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="n">arg</span><span class="o">=</span><span class="s1">'one'</span><span class="p">,</span> <span class="n">arg2</span><span class="o">=</span><span class="s1">'two'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">kall</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">call_args</span>
|
||
<span class="gp">>>> </span><span class="n">kall</span><span class="o">.</span><span class="n">args</span>
|
||
<span class="go">(1, 2, 3)</span>
|
||
<span class="gp">>>> </span><span class="n">kall</span><span class="o">.</span><span class="n">kwargs</span>
|
||
<span class="go">{'arg': 'one', 'arg2': 'two'}</span>
|
||
<span class="gp">>>> </span><span class="n">kall</span><span class="o">.</span><span class="n">args</span> <span class="ow">is</span> <span class="n">kall</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">kall</span><span class="o">.</span><span class="n">kwargs</span> <span class="ow">is</span> <span class="n">kall</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">foo</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="n">arg</span><span class="o">=</span><span class="s1">'two'</span><span class="p">,</span> <span class="n">arg2</span><span class="o">=</span><span class="s1">'three'</span><span class="p">)</span>
|
||
<span class="go"><MagicMock name='mock.foo()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">kall</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">mock_calls</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="gp">>>> </span><span class="n">name</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">kall</span>
|
||
<span class="gp">>>> </span><span class="n">name</span>
|
||
<span class="go">'foo'</span>
|
||
<span class="gp">>>> </span><span class="n">args</span>
|
||
<span class="go">(4, 5, 6)</span>
|
||
<span class="gp">>>> </span><span class="n">kwargs</span>
|
||
<span class="go">{'arg': 'two', 'arg2': 'three'}</span>
|
||
<span class="gp">>>> </span><span class="n">name</span> <span class="ow">is</span> <span class="n">m</span><span class="o">.</span><span class="n">mock_calls</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="create-autospec">
|
||
<h3>create_autospec<a class="headerlink" href="#create-autospec" title="永久链接至标题">¶</a></h3>
|
||
<dl class="function">
|
||
<dt id="unittest.mock.create_autospec">
|
||
<code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">create_autospec</code><span class="sig-paren">(</span><em class="sig-param">spec</em>, <em class="sig-param">spec_set=False</em>, <em class="sig-param">instance=False</em>, <em class="sig-param">**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.create_autospec" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>使用另一对象作为 spec 来创建 mock 对象。 mock 的属性将使用 <em>spec</em> 对象上的对应属性作为其 spec。</p>
|
||
<p>被模拟的函数或方法的参数将会被检查以确保它们是附带了正确的签名被调用的。</p>
|
||
<p>如果 <em>spec_set</em> 为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 则尝试设置不存在于 spec 对象中的属性将引发 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a>。</p>
|
||
<p>如果将类用作 spec 则 mock(该类的实例)的返回值将为这个 spec。 你可以通过传入 <code class="docutils literal notranslate"><span class="pre">instance=True</span></code> 来将某个类用作一个实例对象的 spec。 被返回的 mock 将仅在该 mock 的实例为可调用对象时才会是可调用对象。</p>
|
||
<p><a class="reference internal" href="#unittest.mock.create_autospec" title="unittest.mock.create_autospec"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_autospec()</span></code></a> 也接受被传入所创建 mock 的构造器的任意关键字参数。</p>
|
||
</dd></dl>
|
||
|
||
<p>请参阅 <a class="reference internal" href="#auto-speccing"><span class="std std-ref">自动 spec</span></a> 来了解如何通过 <a class="reference internal" href="#unittest.mock.create_autospec" title="unittest.mock.create_autospec"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_autospec()</span></code></a> 以及 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 的 <em>autospec</em> 参数来自动设置 spec。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>如果目标为异步函数那么 <a class="reference internal" href="#unittest.mock.create_autospec" title="unittest.mock.create_autospec"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_autospec()</span></code></a> 现在将返回一个 <a class="reference internal" href="#unittest.mock.AsyncMock" title="unittest.mock.AsyncMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">AsyncMock</span></code></a>。</p>
|
||
</div>
|
||
</section>
|
||
<section id="any">
|
||
<h3>ANY<a class="headerlink" href="#any" title="永久链接至标题">¶</a></h3>
|
||
<dl class="data">
|
||
<dt id="unittest.mock.ANY">
|
||
<code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">ANY</code><a class="headerlink" href="#unittest.mock.ANY" title="永久链接至目标">¶</a></dt>
|
||
<dd></dd></dl>
|
||
|
||
<p>有时你可能需要设置关于要模拟的调用中的 <em>某些</em> 参数的断言,但是又不想理会其他参数或者想要从 <a class="reference internal" href="#unittest.mock.Mock.call_args" title="unittest.mock.Mock.call_args"><code class="xref py py-attr docutils literal notranslate"><span class="pre">call_args</span></code></a> 中单独拿出它们并针对它们设置更复杂的断言。</p>
|
||
<p>为了忽略某些参数你可以传入与 <em>任意对象</em> 相等的对象。 这样再调用 <a class="reference internal" href="#unittest.mock.Mock.assert_called_with" title="unittest.mock.Mock.assert_called_with"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_called_with()</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.assert_called_once_with" title="unittest.mock.Mock.assert_called_once_with"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_called_once_with()</span></code></a> 时无论传入什么参数都将执行成功。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="nb">object</span><span class="p">())</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="n">ANY</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#unittest.mock.ANY" title="unittest.mock.ANY"><code class="xref py py-data docutils literal notranslate"><span class="pre">ANY</span></code></a> 也可被用在与 <a class="reference internal" href="#unittest.mock.Mock.mock_calls" title="unittest.mock.Mock.mock_calls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">mock_calls</span></code></a> 这样的调用列表相比较的场合:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MagicMock</span><span class="p">(</span><span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="p">(</span><span class="nb">object</span><span class="p">())</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">mock_calls</span> <span class="o">==</span> <span class="p">[</span><span class="n">call</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="n">call</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">ANY</span><span class="p">]</span>
|
||
<span class="go">True</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="filter-dir">
|
||
<h3>FILTER_DIR<a class="headerlink" href="#filter-dir" title="永久链接至标题">¶</a></h3>
|
||
<dl class="data">
|
||
<dt id="unittest.mock.FILTER_DIR">
|
||
<code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">FILTER_DIR</code><a class="headerlink" href="#unittest.mock.FILTER_DIR" title="永久链接至目标">¶</a></dt>
|
||
<dd></dd></dl>
|
||
|
||
<p><a class="reference internal" href="#unittest.mock.FILTER_DIR" title="unittest.mock.FILTER_DIR"><code class="xref py py-data docutils literal notranslate"><span class="pre">FILTER_DIR</span></code></a> 是一个控制 mock 对象响应 <a class="reference internal" href="functions.html#dir" title="dir"><code class="xref py py-func docutils literal notranslate"><span class="pre">dir()</span></code></a> 的方式的模块级变量(只适用于 Python 2.6 之后的版本)。 默认值为 <code class="docutils literal notranslate"><span class="pre">True</span></code>,这将使用下文描述的过滤操作,以便只显示有用的成员。 如果你不想要这样的过滤,或是出于诊断目的需要将其关闭,则应设置 <code class="docutils literal notranslate"><span class="pre">mock.FILTER_DIR</span> <span class="pre">=</span> <span class="pre">False</span></code>。</p>
|
||
<p>当启用过滤时,<code class="docutils literal notranslate"><span class="pre">dir(some_mock)</span></code> 将只显示有用的属性并将包括正常情况下不会被显示的任何动态创建的属性。 如果 mock 是使用 <em>spec</em> (当然也可以是 <em>autospec</em>) 创建的则原有的所有属性都将被显示,即使它们还未被访问过:</p>
|
||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">dir</span><span class="p">(</span><span class="n">Mock</span><span class="p">())</span>
|
||
<span class="go">['assert_any_call',</span>
|
||
<span class="go"> 'assert_called',</span>
|
||
<span class="go"> 'assert_called_once',</span>
|
||
<span class="go"> 'assert_called_once_with',</span>
|
||
<span class="go"> 'assert_called_with',</span>
|
||
<span class="go"> 'assert_has_calls',</span>
|
||
<span class="go"> 'assert_not_called',</span>
|
||
<span class="go"> 'attach_mock',</span>
|
||
<span class="go"> ...</span>
|
||
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">urllib</span> <span class="kn">import</span> <span class="n">request</span>
|
||
<span class="gp">>>> </span><span class="nb">dir</span><span class="p">(</span><span class="n">Mock</span><span class="p">(</span><span class="n">spec</span><span class="o">=</span><span class="n">request</span><span class="p">))</span>
|
||
<span class="go">['AbstractBasicAuthHandler',</span>
|
||
<span class="go"> 'AbstractDigestAuthHandler',</span>
|
||
<span class="go"> 'AbstractHTTPHandler',</span>
|
||
<span class="go"> 'BaseHandler',</span>
|
||
<span class="go"> ...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>许多不太有用的(是 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 的而不是被模拟对象的私有成员)开头带有下划线和双下划线的属性已从在 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 上对 <a class="reference internal" href="functions.html#dir" title="dir"><code class="xref py py-func docutils literal notranslate"><span class="pre">dir()</span></code></a> 的调用的结果中被过滤。 如果你不喜欢此行为你可以通过设置模块级开关 <a class="reference internal" href="#unittest.mock.FILTER_DIR" title="unittest.mock.FILTER_DIR"><code class="xref py py-data docutils literal notranslate"><span class="pre">FILTER_DIR</span></code></a> 来将其关闭:</p>
|
||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">unittest</span> <span class="kn">import</span> <span class="n">mock</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">FILTER_DIR</span> <span class="o">=</span> <span class="kc">False</span>
|
||
<span class="gp">>>> </span><span class="nb">dir</span><span class="p">(</span><span class="n">mock</span><span class="o">.</span><span class="n">Mock</span><span class="p">())</span>
|
||
<span class="go">['_NonCallableMock__get_return_value',</span>
|
||
<span class="go"> '_NonCallableMock__get_side_effect',</span>
|
||
<span class="go"> '_NonCallableMock__return_value_doc',</span>
|
||
<span class="go"> '_NonCallableMock__set_return_value',</span>
|
||
<span class="go"> '_NonCallableMock__set_side_effect',</span>
|
||
<span class="go"> '__call__',</span>
|
||
<span class="go"> '__class__',</span>
|
||
<span class="go"> ...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>或者你也可以直接使用 <code class="docutils literal notranslate"><span class="pre">vars(my_mock)</span></code> (实例成员) 和 <code class="docutils literal notranslate"><span class="pre">dir(type(my_mock))</span></code> (类型成员) 来忽略 <code class="xref py py-data docutils literal notranslate"><span class="pre">mock.FILTER_DIR</span></code> 设置绕过过滤。</p>
|
||
</section>
|
||
<section id="mock-open">
|
||
<h3>mock_open<a class="headerlink" href="#mock-open" title="永久链接至标题">¶</a></h3>
|
||
<dl class="function">
|
||
<dt id="unittest.mock.mock_open">
|
||
<code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">mock_open</code><span class="sig-paren">(</span><em class="sig-param">mock=None</em>, <em class="sig-param">read_data=None</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.mock_open" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>创建 mock 来代替使用 <a class="reference internal" href="functions.html#open" title="open"><code class="xref py py-func docutils literal notranslate"><span class="pre">open()</span></code></a> 的辅助函数。 它对于 <a class="reference internal" href="functions.html#open" title="open"><code class="xref py py-func docutils literal notranslate"><span class="pre">open()</span></code></a> 被直接调用或被用作上下文管理器的情况都适用。</p>
|
||
<p><em>mock</em> 参数是要配置的 mock 对象。 如为 <code class="docutils literal notranslate"><span class="pre">None</span></code> (默认值) 则将为你创建一个 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a>,其 API 会被限制为可用于标准文件处理的方法或属性。</p>
|
||
<p><em>read_data</em> 是供文件处理的 <code class="xref py py-meth docutils literal notranslate"><span class="pre">read()</span></code>, <a class="reference internal" href="io.html#io.IOBase.readline" title="io.IOBase.readline"><code class="xref py py-meth docutils literal notranslate"><span class="pre">readline()</span></code></a> 和 <a class="reference internal" href="io.html#io.IOBase.readlines" title="io.IOBase.readlines"><code class="xref py py-meth docutils literal notranslate"><span class="pre">readlines()</span></code></a> 方法返回的字符串。 调用这些方法将会从 <em>read_data</em> 获取数据直到它被耗尽。 对这些方法的模拟是相当简化的:每次 <em>mock</em> 被调用时,<em>read_data</em> 都将从头开始。 如果你需要对你提供给测试代码的数据有更多控制那么你将需要自行定制这个 mock。 如果这还不够用,那么通过一些 <a class="reference external" href="https://pypi.org">PyPI</a> 上的内存文件系统包可以提供更真实的测试文件系统。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.4 版更改: </span>增加了对 <a class="reference internal" href="io.html#io.IOBase.readline" title="io.IOBase.readline"><code class="xref py py-meth docutils literal notranslate"><span class="pre">readline()</span></code></a> 和 <a class="reference internal" href="io.html#io.IOBase.readlines" title="io.IOBase.readlines"><code class="xref py py-meth docutils literal notranslate"><span class="pre">readlines()</span></code></a> 的支持。 对 <code class="xref py py-meth docutils literal notranslate"><span class="pre">read()</span></code> 的模拟被改为消耗 <em>read_data</em> 而不是每次调用时返回它。</p>
|
||
</div>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.5 版更改: </span><em>read_data</em> 现在会在每次 <em>mock</em> 的调用时重置。</p>
|
||
</div>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>为实现增加了 <a class="reference internal" href="../reference/datamodel.html#object.__iter__" title="object.__iter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__iter__()</span></code></a> 以使迭代操作(例如在 for 循环中)能正确地消耗 <em>read_data</em>。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<p>将 <a class="reference internal" href="functions.html#open" title="open"><code class="xref py py-func docutils literal notranslate"><span class="pre">open()</span></code></a> 用作上下文管理器一确保你的文件处理被正确关闭的最佳方式因而十分常用:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'/some/path'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
|
||
<span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'something'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这里的问题在于即使你模拟了对 <a class="reference internal" href="functions.html#open" title="open"><code class="xref py py-func docutils literal notranslate"><span class="pre">open()</span></code></a> 的调用但被用作上下文管理器(并调用其 <a class="reference internal" href="../reference/datamodel.html#object.__enter__" title="object.__enter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__enter__()</span></code></a> 和 <a class="reference internal" href="../reference/datamodel.html#object.__exit__" title="object.__exit__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__exit__()</span></code></a> 方法)的也是 <em>被返回的对象</em>。</p>
|
||
<p>通过 <a class="reference internal" href="#unittest.mock.MagicMock" title="unittest.mock.MagicMock"><code class="xref py py-class docutils literal notranslate"><span class="pre">MagicMock</span></code></a> 来模拟上下文管理器是十分常见且十分麻烦的因此需要使用一个辅助函数。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">mock_open</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.open'</span><span class="p">,</span> <span class="n">m</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">h</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="n">h</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'some stuff'</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">mock_calls</span>
|
||
<span class="go">[call('foo', 'w'),</span>
|
||
<span class="go"> call().__enter__(),</span>
|
||
<span class="go"> call().write('some stuff'),</span>
|
||
<span class="go"> call().__exit__(None, None, None)]</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">handle</span> <span class="o">=</span> <span class="n">m</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">handle</span><span class="o">.</span><span class="n">write</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="s1">'some stuff'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>以及针对读取文件:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.open'</span><span class="p">,</span> <span class="n">mock_open</span><span class="p">(</span><span class="n">read_data</span><span class="o">=</span><span class="s1">'bibble'</span><span class="p">))</span> <span class="k">as</span> <span class="n">m</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">)</span> <span class="k">as</span> <span class="n">h</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="n">result</span> <span class="o">=</span> <span class="n">h</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">result</span> <span class="o">==</span> <span class="s1">'bibble'</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="autospeccing">
|
||
<span id="auto-speccing"></span><h3>自动 spec<a class="headerlink" href="#autospeccing" title="永久链接至标题">¶</a></h3>
|
||
<p>自动 spec 是基于现有 mock 的 <code class="xref py py-attr docutils literal notranslate"><span class="pre">spec</span></code> 特性。 它将 mock 的 api 限制为原始对象 (spec) 的 api,但它是递归(惰性实现)的因而 mock 的属性只有与 spec 的属性相同的 api。 除此之外被模块的函数 / 方法具有与原对应物相同的调用签名因此如果它们被不正确地调用时会引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a>。</p>
|
||
<p>在我开始解释自动 spec 如何运作之前,先说明一下它的必要性。</p>
|
||
<p><a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 是一个非常强大而灵活的对象,但当它被用来模拟来自被测试系统的对象时有两个缺陷。 其中一个缺陷是 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 的 api 特有的而另一个则是使用 mock 对象时普遍存在的问题。</p>
|
||
<p>第一个问题为 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 所专属。 <a class="reference internal" href="#unittest.mock.Mock" title="unittest.mock.Mock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Mock</span></code></a> 具有两个特别好用的断言方法: <a class="reference internal" href="#unittest.mock.Mock.assert_called_with" title="unittest.mock.Mock.assert_called_with"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_called_with()</span></code></a> 和 <a class="reference internal" href="#unittest.mock.Mock.assert_called_once_with" title="unittest.mock.Mock.assert_called_once_with"><code class="xref py py-meth docutils literal notranslate"><span class="pre">assert_called_once_with()</span></code></a>。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'Thing'</span><span class="p">,</span> <span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">AssertionError</span>: <span class="n">Expected 'mock' to be called once. Called 2 times.</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>因为 mock 会根据需要自动创建属性,并允许你附带任意参数调用它们,所以如果你写错了这两个断言方法则你的断言将会失效:</p>
|
||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'Thing'</span><span class="p">,</span> <span class="n">return_value</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assret_called_once_with</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>你的测试将因这个拼写错误而静默并且错误地通过。</p>
|
||
<p>第二个问题是 mock 操作中普遍存在的。 如果你重构了你的部分代码,例如修改了一些成员的名称等等,则代码中任何仍在使用 <em>旧 api</em> 但其使用的是 mock 而非真实对象的测试仍将通过。 这意味着即使你的代码已被破坏你的测试却仍可能全部通过。</p>
|
||
<p>请注意这是为什么你在单元测试之外还需要集成测试的原因之一。 孤立地测试每个部分时全都正常而顺滑,但是如果你没有测试你的各个单元“联成一体”的情况如何那么就仍然存在测试可以发现大量错误的空间。</p>
|
||
<p><code class="xref py py-mod docutils literal notranslate"><span class="pre">mock</span></code> 已经提供了一个对此有帮助的特性,称为 spec 控制。 如果你使用类或实例作为一个 mock 的 <code class="xref py py-attr docutils literal notranslate"><span class="pre">spec</span></code> 那么你将仅能访问 mock 中只存在于实际的类中的属性。</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">urllib</span> <span class="kn">import</span> <span class="n">request</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">(</span><span class="n">spec</span><span class="o">=</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">assret_called_with</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">AttributeError</span>: <span class="n">Mock object has no attribute 'assret_called_with'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这个 spec 仅会应用于 mock 本身,因此对于 mock 中的任意方法我们仍然面临相同的问题:</p>
|
||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">has_data</span><span class="p">()</span>
|
||
<span class="go"><mock.Mock object at 0x...></span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">has_data</span><span class="o">.</span><span class="n">assret_called_with</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>自动 spec 解决了这个问题。 你可以将 <code class="docutils literal notranslate"><span class="pre">autospec=True</span></code> 传给 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> / <a class="reference internal" href="#unittest.mock.patch.object" title="unittest.mock.patch.object"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch.object()</span></code></a> 或是使用 <a class="reference internal" href="#unittest.mock.create_autospec" title="unittest.mock.create_autospec"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_autospec()</span></code></a> 函数来创建带有 spec 的 mock。 如果你是将 <code class="docutils literal notranslate"><span class="pre">autospec=True</span></code> 参数传给 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 那么被替代的那个对象将被用作 spec 对象。 因为 spec 控制是“惰性地”执行的(spec 在 mock 中的属性被访问时才会被创建)所以即使是非常复杂或深度嵌套的对象(例如需要导入本身已导入了多个模块的模块)你也可以使用它而不会有太大的性能损失。</p>
|
||
<p>以下是一个实际应用的示例:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">urllib</span> <span class="kn">import</span> <span class="n">request</span>
|
||
<span class="gp">>>> </span><span class="n">patcher</span> <span class="o">=</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.request'</span><span class="p">,</span> <span class="n">autospec</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock_request</span> <span class="o">=</span> <span class="n">patcher</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">request</span> <span class="ow">is</span> <span class="n">mock_request</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">mock_request</span><span class="o">.</span><span class="n">Request</span>
|
||
<span class="go"><MagicMock name='request.Request' spec='Request' id='...'></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>你可以看到 <code class="xref py py-class docutils literal notranslate"><span class="pre">request.Request</span></code> 有一个 spec。 <code class="xref py py-class docutils literal notranslate"><span class="pre">request.Request</span></code> 的构造器接受两个参数 (其中一个是 <em>self</em>)。 如果我们尝试不正确地调用它则将导致:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">req</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">TypeError</span>: <span class="n"><lambda>() takes at least 2 arguments (1 given)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>该 spec 也将应用于被实例化的类(即附带i.e. the return value of spec 的 mock 的返回值):</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">req</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">req</span>
|
||
<span class="go"><NonCallableMagicMock name='request.Request()' spec='Request' id='...'></span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="xref py py-class docutils literal notranslate"><span class="pre">Request</span></code> 对象是不可调用对象,因此实例化我们的被模拟 <code class="xref py py-class docutils literal notranslate"><span class="pre">request.Request</span></code> 的返回值是一个不可调用的 mock。 有了这个 spec 我们的断言中出现任何拼写问题都将引发正确的错误:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">req</span><span class="o">.</span><span class="n">add_header</span><span class="p">(</span><span class="s1">'spam'</span><span class="p">,</span> <span class="s1">'eggs'</span><span class="p">)</span>
|
||
<span class="go"><MagicMock name='request.Request().add_header()' id='...'></span>
|
||
<span class="gp">>>> </span><span class="n">req</span><span class="o">.</span><span class="n">add_header</span><span class="o">.</span><span class="n">assret_called_with</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">AttributeError</span>: <span class="n">Mock object has no attribute 'assret_called_with'</span>
|
||
<span class="gp">>>> </span><span class="n">req</span><span class="o">.</span><span class="n">add_header</span><span class="o">.</span><span class="n">assert_called_with</span><span class="p">(</span><span class="s1">'spam'</span><span class="p">,</span> <span class="s1">'eggs'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在许多情况下你将只需将In many cases you will just be able to add <code class="docutils literal notranslate"><span class="pre">autospec=True</span></code> 添加到你现有的 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 调用中即可防止拼写错误和 api 变化所导致的问题。</p>
|
||
<p>除了通过 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 来使用 <em>autospec</em> 还有一个 <a class="reference internal" href="#unittest.mock.create_autospec" title="unittest.mock.create_autospec"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_autospec()</span></code></a> 可以直接创建带有自动 spec 的 mock:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">urllib</span> <span class="kn">import</span> <span class="n">request</span>
|
||
<span class="gp">>>> </span><span class="n">mock_request</span> <span class="o">=</span> <span class="n">create_autospec</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock_request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="s1">'bar'</span><span class="p">)</span>
|
||
<span class="go"><NonCallableMagicMock name='mock.Request()' spec='Request' id='...'></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>不过这并非没有缺点和限制,这也就是为什么它不是默认行为。 为了知道在 spec 对象上有哪些属性是可用的,autospec 必须对 spec 进行自省(访问其属性)。 当你遍历 mock 上的属性时在原始对象上的对应遍历也将在底层进行。 如果你的任何带 spec 的对象具有可触发代码执行的特征属性或描述器则你可能会无法使用 autospec。 在另一方面更好的的做法是将你的对象设计为可以安全地执行自省 <a class="footnote-reference brackets" href="#id12" id="id11">4</a>。</p>
|
||
<p>一个更严重的问题在于实例属性往往是在 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 方法中被创建而在类中完全不存在。 <em>autospec</em> 无法获取动态创建的属性而使得 api 被限制于可见的属性。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Something</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="mi">33</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.Something'</span><span class="p">,</span> <span class="n">autospec</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">thing</span> <span class="o">=</span> <span class="n">Something</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="n">thing</span><span class="o">.</span><span class="n">a</span>
|
||
<span class="gp">...</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">AttributeError</span>: <span class="n">Mock object has no attribute 'a'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>要解决这个问题有几种不同的方式。 最容易但多少有些烦扰的方式是简单地在 mock 创建完成后再设置所需的属性。 Just because <em>autospec</em> 只是不允许你获取不存在于 spec 上的属性但并不会阻止你设置它们:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.Something'</span><span class="p">,</span> <span class="n">autospec</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">thing</span> <span class="o">=</span> <span class="n">Something</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="n">thing</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="mi">33</span>
|
||
<span class="gp">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><em>spec</em> 和 <em>autospec</em> 都有更严格的版本 <em>确实能</em> 阻止你设置不存在的属性。 这在你希望确保你的代码只能 <em>设置</em> 有效的属性时也很有用,但显然它会阻止下面这个特定的应用场景:</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">with</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.Something'</span><span class="p">,</span> <span class="n">autospec</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">spec_set</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">thing</span> <span class="o">=</span> <span class="n">Something</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="n">thing</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="mi">33</span>
|
||
<span class="gp">...</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">AttributeError</span>: <span class="n">Mock object has no attribute 'a'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>解决此问题的最好方式可能是添加类属性作为在 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 中初始化的实例属性的默认值。 请注意如果你只在 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 中设置默认属性那么通过类属性来提供它们(当然会在实例之间共享)也将有更快的速度。 例如</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Something</span><span class="p">:</span>
|
||
<span class="n">a</span> <span class="o">=</span> <span class="mi">33</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这带来了另一个问题。 为今后将变为不同类型对象的那些成员提供默认值 <code class="docutils literal notranslate"><span class="pre">None</span></code> 是比较常见的做法。 <code class="docutils literal notranslate"><span class="pre">None</span></code> 作为 spec 是没有用处的,因为它会使你无法访问 <em>any</em> 任何属性或方法。 由于 <code class="docutils literal notranslate"><span class="pre">None</span></code> 作为 spec 将 <em>永远不会</em> 有任何用处,并且有可能要指定某个通常为其他类型的成员,因此 autospec 不会为被设为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 的成员使用 spec。 它们将为普通的 mock (嗯 —— 应为 MagicMocks):</p>
|
||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Something</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="n">member</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">create_autospec</span><span class="p">(</span><span class="n">Something</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">member</span><span class="o">.</span><span class="n">foo</span><span class="o">.</span><span class="n">bar</span><span class="o">.</span><span class="n">baz</span><span class="p">()</span>
|
||
<span class="go"><MagicMock name='mock.member.foo.bar.baz()' id='...'></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果你不喜欢修改你的生产类来添加默认值那么还有其他的选项。 其中之一是简单地使用一个实例而非类作为 spec。 另一选项则是创建一个生产类的子类并向该子类添加默认值而不影响到生产类。 这两个选项都需要你使用一个替代对象作为 spec。 值得庆幸的是 <a class="reference internal" href="#unittest.mock.patch" title="unittest.mock.patch"><code class="xref py py-func docutils literal notranslate"><span class="pre">patch()</span></code></a> 支持这样做 —— 你可以简单地传入替代对象作为 <em>autospec</em> 参数:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Something</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="mi">33</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">SomethingForTest</span><span class="p">(</span><span class="n">Something</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">a</span> <span class="o">=</span> <span class="mi">33</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">p</span> <span class="o">=</span> <span class="n">patch</span><span class="p">(</span><span class="s1">'__main__.Something'</span><span class="p">,</span> <span class="n">autospec</span><span class="o">=</span><span class="n">SomethingForTest</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">a</span>
|
||
<span class="go"><NonCallableMagicMock name='Something.a' spec='int' id='...'></span>
|
||
</pre></div>
|
||
</div>
|
||
<dl class="footnote brackets">
|
||
<dt class="label" id="id12"><span class="brackets"><a class="fn-backref" href="#id11">4</a></span></dt>
|
||
<dd><p>这仅适用于类或已实例化的对象。 调用一个被模拟的类来创建一个 mock 实例 <em>不会</em> 创建真的实例。 只有属性查找 —— 以及对 <a class="reference internal" href="functions.html#dir" title="dir"><code class="xref py py-func docutils literal notranslate"><span class="pre">dir()</span></code></a> 的调用 —— 会被执行。</p>
|
||
</dd>
|
||
</dl>
|
||
</section>
|
||
<section id="sealing-mocks">
|
||
<h3>将 mock 封包<a class="headerlink" href="#sealing-mocks" title="永久链接至标题">¶</a></h3>
|
||
<dl class="function">
|
||
<dt id="unittest.mock.seal">
|
||
<code class="sig-prename descclassname">unittest.mock.</code><code class="sig-name descname">seal</code><span class="sig-paren">(</span><em class="sig-param">mock</em><span class="sig-paren">)</span><a class="headerlink" href="#unittest.mock.seal" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>封包将在访问被封包的 mock 的属性或其任何已经被递归地模拟的属性时禁止自动创建 mock。</p>
|
||
<p>如果一个带有名称或 spec 的 mock 实例被分配给一个属性则将不会在封包链中处理它。 这可以防止人们对 mock 对象的固定部分执行封包。</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">mock</span> <span class="o">=</span> <span class="n">Mock</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">submock</span><span class="o">.</span><span class="n">attribute1</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">not_submock</span> <span class="o">=</span> <span class="n">mock</span><span class="o">.</span><span class="n">Mock</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">"sample_name"</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">seal</span><span class="p">(</span><span class="n">mock</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">new_attribute</span> <span class="c1"># This will raise AttributeError.</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">submock</span><span class="o">.</span><span class="n">attribute2</span> <span class="c1"># This will raise AttributeError.</span>
|
||
<span class="gp">>>> </span><span class="n">mock</span><span class="o">.</span><span class="n">not_submock</span><span class="o">.</span><span class="n">attribute2</span> <span class="c1"># This won't raise.</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.7 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<h3><a href="../contents.html">目录</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest.mock</span></code> --- 模拟对象库</a><ul>
|
||
<li><a class="reference internal" href="#quick-guide">快速上手</a></li>
|
||
<li><a class="reference internal" href="#the-mock-class">Mock 类</a><ul>
|
||
<li><a class="reference internal" href="#calling">调用</a></li>
|
||
<li><a class="reference internal" href="#deleting-attributes">删除属性</a></li>
|
||
<li><a class="reference internal" href="#mock-names-and-the-name-attribute">Mock 的名称与 name 属性</a></li>
|
||
<li><a class="reference internal" href="#attaching-mocks-as-attributes">附加 Mock 作为属性</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#the-patchers">patch 装饰器</a><ul>
|
||
<li><a class="reference internal" href="#patch">patch</a></li>
|
||
<li><a class="reference internal" href="#patch-object">patch.object</a></li>
|
||
<li><a class="reference internal" href="#patch-dict">patch.dict</a></li>
|
||
<li><a class="reference internal" href="#patch-multiple">patch.multiple</a></li>
|
||
<li><a class="reference internal" href="#patch-methods-start-and-stop">补丁方法: start 和 stop</a></li>
|
||
<li><a class="reference internal" href="#patch-builtins">为内置对象打补丁</a></li>
|
||
<li><a class="reference internal" href="#test-prefix">TEST_PREFIX</a></li>
|
||
<li><a class="reference internal" href="#nesting-patch-decorators">嵌套补丁装饰器</a></li>
|
||
<li><a class="reference internal" href="#where-to-patch">补丁的目标</a></li>
|
||
<li><a class="reference internal" href="#patching-descriptors-and-proxy-objects">对描述器和代理对象打补丁</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#magicmock-and-magic-method-support">MagicMock 与魔术方法支持</a><ul>
|
||
<li><a class="reference internal" href="#mocking-magic-methods">模拟魔术方法</a></li>
|
||
<li><a class="reference internal" href="#magic-mock">MagicMock</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#helpers">辅助对象</a><ul>
|
||
<li><a class="reference internal" href="#sentinel">sentinel</a></li>
|
||
<li><a class="reference internal" href="#default">DEFAULT</a></li>
|
||
<li><a class="reference internal" href="#call">call</a></li>
|
||
<li><a class="reference internal" href="#create-autospec">create_autospec</a></li>
|
||
<li><a class="reference internal" href="#any">ANY</a></li>
|
||
<li><a class="reference internal" href="#filter-dir">FILTER_DIR</a></li>
|
||
<li><a class="reference internal" href="#mock-open">mock_open</a></li>
|
||
<li><a class="reference internal" href="#autospeccing">自动 spec</a></li>
|
||
<li><a class="reference internal" href="#sealing-mocks">将 mock 封包</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="unittest.html"
|
||
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest</span></code> --- 单元测试框架</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="unittest.mock-examples.html"
|
||
title="下一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">unittest.mock</span></code> --- 上手指南</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<h3>本页</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">报告 Bug</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.8/Doc/library/unittest.mock.rst"
|
||
rel="nofollow">显示源代码
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>导航</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="总目录"
|
||
>索引</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python 模块索引"
|
||
>模块</a> |</li>
|
||
<li class="right" >
|
||
<a href="unittest.mock-examples.html" title="unittest.mock --- 上手指南"
|
||
>下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="unittest.html" title="unittest --- 单元测试框架"
|
||
>上一页</a> |</li>
|
||
|
||
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.8.20 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="development.html" >开发工具</a> »</li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
|
||
<input type="submit" value="转向" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
<div class="footer">
|
||
© <a href="../copyright.html">版权所有</a> 2001-2024, Python Software Foundation.
|
||
<br />
|
||
This page is licensed under the Python Software Foundation License Version 2.
|
||
<br />
|
||
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
|
||
<br />
|
||
|
||
<br />
|
||
|
||
The Python Software Foundation is a non-profit corporation.
|
||
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
||
<br />
|
||
<br />
|
||
|
||
最后更新于 12月 09, 2024.
|
||
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
|
||
<br />
|
||
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.4.4.
|
||
</div>
|
||
|
||
</body>
|
||
</html> |