test_ok2/doc/en/monkeypatch.rst

87 lines
3.1 KiB
ReStructuredText
Raw Normal View History

Monkeypatching/mocking modules and environments
================================================================
.. currentmodule:: _pytest.monkeypatch
Sometimes tests need to invoke functionality which depends
on global settings or which invokes code which cannot be easily
2016-07-21 09:05:49 +08:00
tested such as network access. The ``monkeypatch`` fixture
helps you to safely set/delete an attribute, dictionary item or
environment variable or to modify ``sys.path`` for importing.
See the `monkeypatch blog post`_ for some introduction material
and a discussion of its motivation.
.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
2016-07-21 09:05:49 +08:00
Simple example: monkeypatching functions
---------------------------------------------------
If you want to pretend that ``os.expanduser`` returns a certain
directory, you can use the :py:meth:`monkeypatch.setattr` method to
patch this function before calling into a function which uses it::
# content of test_module.py
import os.path
def getssh(): # pseudo application code
return os.path.join(os.path.expanduser("~admin"), '.ssh')
def test_mytest(monkeypatch):
def mockreturn(path):
return '/abc'
monkeypatch.setattr(os.path, 'expanduser', mockreturn)
x = getssh()
assert x == '/abc/.ssh'
Here our test function monkeypatches ``os.path.expanduser`` and
2017-01-01 01:54:47 +08:00
then calls into a function that calls it. After the test function
finishes the ``os.path.expanduser`` modification will be undone.
example: preventing "requests" from remote operations
------------------------------------------------------
If you want to prevent the "requests" library from performing http
requests in all your tests, you can do::
# content of conftest.py
import pytest
@pytest.fixture(autouse=True)
def no_requests(monkeypatch):
2014-08-19 03:44:34 +08:00
monkeypatch.delattr("requests.sessions.Session.request")
This autouse fixture will be executed for each test function and it
will delete the method ``request.session.Session.request``
so that any attempts within tests to create http requests will fail.
.. note::
Be advised that it is not recommended to patch builtin functions such as ``open``,
``compile``, etc., because it might break pytest's internals. If that's
unavoidable, passing ``--tb=native``, ``--assert=plain`` and ``--capture=no`` might
2017-01-01 01:54:47 +08:00
help although there's no guarantee.
2018-04-11 01:30:10 +08:00
2018-04-13 21:00:07 +08:00
.. note::
2018-04-11 01:30:10 +08:00
2018-04-13 21:00:07 +08:00
Mind that patching ``stdlib`` functions and some third-party libraries used by pytest
might break pytest itself, therefore in those cases it is recommended to use
:meth:`MonkeyPatch.context` to limit the patching to the block you want tested:
2018-04-11 01:30:10 +08:00
2018-04-13 21:00:07 +08:00
.. code-block:: python
2018-04-11 01:30:10 +08:00
import functools
def test_partial(monkeypatch):
with monkeypatch.context() as m:
m.setattr(functools, "partial", 3)
assert functools.partial == 3
2018-04-13 21:00:07 +08:00
See issue `#3290 <https://github.com/pytest-dev/pytest/issues/3290>`_ for details.
.. currentmodule:: _pytest.monkeypatch
API Reference
-------------
Consult the docs for the :class:`MonkeyPatch` class.