如何在具有模拟装饰器的测试中使用 pytest capsys?
Posted
技术标签:
【中文标题】如何在具有模拟装饰器的测试中使用 pytest capsys?【英文标题】:How to use pytest capsys on tests that have mocking decorators? 【发布时间】:2019-02-03 06:27:33 【问题描述】:我一直在尝试找到一种同时使用模拟装饰器和 pytest capsys 的方法,但我找不到正确的方法。
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】:如request-mock
's docs中所述:
pytest
有自己的注册和加载自定义设备的方法。requests-mock
提供了一个用pytest
注册的外部夹具,因此只需将其指定为参数即可使用。无需导入requests-mock
,只需安装并指定参数requests_mock
即可。然后,fixture 提供与
requests_mock.Mocker
相同的接口,让您可以按预期使用requests-mock
。>>> 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 ...
所以只需使用requests_mock
夹具而不是装饰器:
def test_with_mock_and_capsys(requests_mock, capsys):
pass
背景
pytest
不能与向测试函数添加位置参数的函数装饰器一起使用。 pytest
考虑所有参数,
functools.partial
绑定;
不替换为 unittest.mock
模拟
被替换为夹具值,如果没有找到适合任何参数的夹具,则会失败。所以像
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
会失败,这正是requests-mock
所做的。一种解决方法是通过关键字 args 传递 mocker:
import pytest
import requests_mock
@requests_mock.Mocker(kw='m')
def test_with_mock_and_fixtures(capsys, **kwargs):
m = kwargs['m']
...
但是既然requests-mock
已经提供了一个fixture,为什么还要使用装饰器呢?
【讨论】:
大家好,我是 requests-mock 的作者。感谢您的回答,我将从现在开始将人们链接到此。你介意我只是将背景 sn-p 复制到文档中吗? 当然,很高兴这个例子有帮助!以上是关于如何在具有模拟装饰器的测试中使用 pytest capsys?的主要内容,如果未能解决你的问题,请参考以下文章