我的用例是这样的:我希望pytest固定装置返回一个类,该类的依赖关系已被模拟以返回不同的可配置值。
测试对象为Subject
类。它取决于模块boto3
。我想对其进行模拟,以便在我调用boto3.client('codepipeline')
时会返回一个模拟对象,该对象配置为以某种方式运行。
出于测试目的,我想在其上调用'foo()'函数并返回可配置的响应。
在这种情况下,我将其配置为返回字符串“ bar”。
我正在尝试将unittest.mock.patch用作pytest固定装置内的上下文管理器,并且无法正常工作。
演示代码:
#subject.py
import boto3
class Subject:
def __init__(self):
self.codepipeline_client = boto3.client('codepipeline')
def foo(self):
return self.codepipeline_client.foo()
#test_subject.py
from unittest.mock import patch, NonCallableMagicMock
import pytest
from expects import expect, equal
import subject
@pytest.fixture
def mocked_subject_factory():
def _boto3_client_mock(aws_service, foo):
client = None
if aws_service == 'codepipeline':
client = NonCallableMagicMock(name='codepipeline_client')
client.foo.return_value = foo
return client
def _factory(foo):
with patch('subject.boto3.client') as mock_client:
mock_client.side_effect = _boto3_client_mock(foo=foo)
yield subject.Subject()
return _factory
class TestSubject:
def test_passing_foo(self, mocked_subject_factory):
s = mocked_subject_factory(foo='mocked foo value')
print(s)
expect(s.foo()).to(equal('mocked foo value'))
如果我运行pytest -s test_subject.py
,我会得到:
================================================= test session starts ==================================================
platform linux -- Python 3.7.0, pytest-3.8.2, py-1.6.0, pluggy-0.7.1
rootdir: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, inifile:
collected 1 item
test_subject.py <generator object mocked_subject_factory.<locals>._factory at 0x7f246255d840>
F
======================================================= FAILURES =======================================================
_____________________________________________ TestSubject.test_passing_foo _____________________________________________
self = <test_subject.TestSubject object at 0x7f24624e0940>
mocked_subject_factory = <function mocked_subject_factory.<locals>._factory at 0x7f24624e36a8>
def test_passing_foo(self, mocked_subject_factory):
s = mocked_subject_factory(foo='mocked foo value')
print(s)
> expect(s.foo()).to(equal('mocked foo value'))
E AttributeError: 'generator' object has no attribute 'foo'
test_subject.py:31: AttributeError
编辑1:我按照注释中的@hoefling的说明进行了以下测试,但结果相同:
from unittest.mock import patch, NonCallableMagicMock
import pytest
from expects import expect, equal
import subject
@pytest.fixture
def mocked_subject_factory():
def _boto3_client_mock(aws_service, foo):
client = None
if aws_service == 'codepipeline':
client = NonCallableMagicMock(name='codepipeline_client')
client.foo.return_value = foo
return client
with patch('subject.boto3.client') as mock_client:
def _factory(foo):
mock_client.side_effect = _boto3_client_mock(foo=foo)
yield subject.Subject()
yield _factory
class TestSubject:
def test_passing_foo(self, mocked_subject_factory):
print(mocked_subject_factory)
s = mocked_subject_factory(foo='mocked foo value')
print(s)
expect(s.foo()).to(equal('mocked foo value'))