How to use pytest capsys on tests that have mocking decorators?

自闭症网瘾萝莉.ら 提交于 2020-02-24 14:40:13

问题


I have being trying to find a way to use mocking decorators and pytest capsys at the same time but I wasn't able to find the right way to do it.

import pytest
import requests_mock


@requests_mock.mock()
def test_with_mock(m):
    pass

def test_with_capsys(capsys):
    pass


# how to write a test that works with both?

回答1:


As stated in the request-mock's docs:

pytest has its own method of registering and loading custom fixtures. requests-mock provides an external fixture registered with pytest such that it is usable simply by specifying it as a parameter. There is no need to import requests-mock it simply needs to be installed and specify the argument requests_mock.

The fixture then provides the same interface as the requests_mock.Mocker letting you use requests-mock as you would expect.

>>> import pytest
>>> import requests

>>> def test_url(requests_mock):
...     requests_mock.get('http://test.com', text='data')
...     assert 'data' == requests.get('http://test.com').text
...

So just use the requests_mock fixture instead of the decorator:

def test_with_mock_and_capsys(requests_mock, capsys):
    pass

Background

pytest doesn't play along with function decorators that add positional arguments to the test function. pytest considers all arguments that

  • aren't bound to an instance or type as in instance or class methods;
  • don't have default values;
  • aren't bound with functools.partial;
  • aren't replaced with unittest.mock mocks

to be replaced with fixture values, and will fail if it doesn't find a suitable fixture for any argument. So stuff like

import functools
import pytest


def deco(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        args += ('spam',)
        return func(*args, **kwargs)
    return wrapper


@deco
def test_spam(spam_arg):
    assert True

will fail, and this is exactly what requests-mock does. A workaround to that would be passing the mocker via keyword args:

import pytest
import requests_mock


@requests_mock.Mocker(kw='m')
def test_with_mock_and_fixtures(capsys, **kwargs):
    m = kwargs['m']
    ...

but since requests-mock already offers a fixture, why bother using the decorator?



来源:https://stackoverflow.com/questions/52060950/how-to-use-pytest-capsys-on-tests-that-have-mocking-decorators

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!