Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.1.x] Add reference to the Where to patch docs in monkeypatch.setattr #10221

Merged
merged 1 commit into from Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 11 additions & 13 deletions doc/en/how-to/monkeypatch.rst
Expand Up @@ -14,18 +14,16 @@ environment variable, or to modify ``sys.path`` for importing.
The ``monkeypatch`` fixture provides these helper methods for safely patching and mocking
functionality in tests:

.. code-block:: python
* :meth:`monkeypatch.setattr(obj, name, value, raising=True) <pytest.MonkeyPatch.setattr>`
* :meth:`monkeypatch.delattr(obj, name, raising=True) <pytest.MonkeyPatch.delattr>`
* :meth:`monkeypatch.setitem(mapping, name, value) <pytest.MonkeyPatch.setitem>`
* :meth:`monkeypatch.delitem(obj, name, raising=True) <pytest.MonkeyPatch.delitem>`
* :meth:`monkeypatch.setenv(name, value, prepend=None) <pytest.MonkeyPatch.setenv>`
* :meth:`monkeypatch.delenv(name, raising=True) <pytest.MonkeyPatch.delenv>`
* :meth:`monkeypatch.syspath_prepend(path) <pytest.MonkeyPatch.syspath_prepend>`
* :meth:`monkeypatch.chdir(path) <pytest.MonkeyPatch.chdir>`
* :meth:`monkeypatch.context() <pytest.MonkeyPatch.context>`

monkeypatch.setattr(obj, name, value, raising=True)
monkeypatch.setattr("somemodule.obj.name", value, raising=True)
monkeypatch.delattr(obj, name, raising=True)
monkeypatch.setitem(mapping, name, value)
monkeypatch.delitem(obj, name, raising=True)
monkeypatch.setenv(name, value, prepend=None)
monkeypatch.delenv(name, raising=True)
monkeypatch.syspath_prepend(path)
monkeypatch.chdir(path)
monkeypatch.context()

All modifications will be undone after the requesting
test function or fixture has finished. The ``raising``
Expand Down Expand Up @@ -64,8 +62,8 @@ and a discussion of its motivation.

.. _`monkeypatch blog post`: https://tetamap.wordpress.com//2009/03/03/monkeypatching-in-unit-tests-done-right/

Simple example: monkeypatching functions
----------------------------------------
Monkeypatching functions
------------------------

Consider a scenario where you are working with user directories. In the context of
testing, you do not want your test to depend on the running user. ``monkeypatch``
Expand Down
37 changes: 31 additions & 6 deletions src/_pytest/monkeypatch.py
Expand Up @@ -40,6 +40,7 @@ def monkeypatch() -> Generator["MonkeyPatch", None, None]:
* :meth:`monkeypatch.delenv(name, raising=True) <pytest.MonkeyPatch.delenv>`
* :meth:`monkeypatch.syspath_prepend(path) <pytest.MonkeyPatch.syspath_prepend>`
* :meth:`monkeypatch.chdir(path) <pytest.MonkeyPatch.chdir>`
* :meth:`monkeypatch.context() <pytest.MonkeyPatch.context>`

All modifications will be undone after the requesting test function or
fixture has finished. The ``raising`` parameter determines if a :class:`KeyError`
Expand Down Expand Up @@ -186,16 +187,40 @@ def setattr(
value: object = notset,
raising: bool = True,
) -> None:
"""Set attribute value on target, memorizing the old value.
"""
Set attribute value on target, memorizing the old value.

For example:

.. code-block:: python

import os

monkeypatch.setattr(os, "getcwd", lambda: "/")

The code above replaces the :func:`os.getcwd` function by a ``lambda`` which
always returns ``"/"``.

For convenience you can specify a string as ``target`` which
For convenience, you can specify a string as ``target`` which
will be interpreted as a dotted import path, with the last part
being the attribute name. For example,
``monkeypatch.setattr("os.getcwd", lambda: "/")``
would set the ``getcwd`` function of the ``os`` module.
being the attribute name:

Raises AttributeError if the attribute does not exist, unless
.. code-block:: python

monkeypatch.setattr("os.getcwd", lambda: "/")

Raises :class:`AttributeError` if the attribute does not exist, unless
``raising`` is set to False.

**Where to patch**

``monkeypatch.setattr`` works by (temporarily) changing the object that a name points to with another one.
There can be many names pointing to any individual object, so for patching to work you must ensure
that you patch the name used by the system under test.

See the section :ref:`Where to patch <python:where-to-patch>` in the :mod:`unittest.mock`
docs for a complete explanation, which is meant for :func:`unittest.mock.patch` but
applies to ``monkeypatch.setattr`` as well.
"""
__tracebackhide__ = True
import inspect
Expand Down