90 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
| 
 | |
| 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
 | |
| 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/
 | |
| 
 | |
| 
 | |
| 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
 | |
| 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):
 | |
|         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
 | |
|     help although there's no guarantee.
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     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:
 | |
| 
 | |
|     .. code-block:: python
 | |
| 
 | |
|         import functools
 | |
| 
 | |
| 
 | |
|         def test_partial(monkeypatch):
 | |
|             with monkeypatch.context() as m:
 | |
|                 m.setattr(functools, "partial", 3)
 | |
|                 assert functools.partial == 3
 | |
| 
 | |
|     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.
 |