在使用unitttest.mock和pytest将一个依赖类模拟到另一个依赖类时,我一直遇到一个问题。
我正在测试接收 GenericAPI 类的类 Card 。 GenericAPI 类具有以下内容:
class GenericAPI(CardAPI):
REQUEST = {
'API': 'xxx',
'CARDS_ENDPOINT': 'xxx',
'DELAY': 0.1,
'ENCODING': 'utf-8',
'HEADER_AUTH': {'Authorization': 'Bearer cs{client_secret}'},
'HEADER_CONTENT': {'Content-Type': 'application/json'},
}
def __init__(self, name):
super().__init__(self)
self.name = name
self._value = None
@classmethod
def get_card(cls, name):
try:
response = requests.get(url=f'{cls.REQUEST["API"]}{cls.REQUEST["CARDS_ENDPOINT"]}?exact={name}')
response.raise_for_status()
return response.json()
except requests.HTTPError as err:
logger.debug(f'Card "{name}" not found. trying fuzzy match. Response: {err}')
try:
response = requests.get(url=f'{cls.REQUEST["API"]}{cls.REQUEST["CARDS_ENDPOINT"]}?fuzzy={name}')
response.raise_for_status()
return response.json()
except requests.HTTPError as err:
logger.debug(f'Card "{name}" not found. Response: {err}')
raise ValueError
@property
def value(self):
return self._value
@value.getter
def value(self):
prices = self.get_card(name=self.name)['prices']
self.value = dict({'foil': prices['usd_foil'], 'non-foil': prices['usd']})
return self._value
@value.setter
def value(self, new_value):
self._value = new_value
与之相关的 Card 类由
定义class Card:
def __new__(cls, *args, **kwargs):
try:
kwargs['external_api'].get_card(name=kwargs['name'])
return super(Card, cls).__new__(cls)
except ValueError:
raise ValueError('Unable to instantiate Card with current value as it is not a valid card')
def __init__(self, name, set_name=None, condition=None, foil=None, external_api=None):
self.name = name
self.set_name = set_name
self.condition = condition
self.foil = foil
self._value = None
self._external_api = external_api
@property
def value(self):
return float(self.value)
@value.getter
def value(self):
card = self._external_api(name=self.name)
price = card.value
if self.foil:
self.value = price['foil']
return self._value
else:
self.value = price['non-foil']
return self._value
@value.setter
def value(self, new_value):
self._value = new_value
测试定义如下:
GOOD_RESPONSE = {'object': 'card', 'id': '6b3a20ac-1860-4513-bb73-35d23b088b04', 'name': 'Mox Opal',
'oracle_id': 'de2440de-e948-4811-903c-0bbe376ff64d', 'multiverse_ids': [397719],
# lots more of info in json
'mtgo_id': 57258, 'prices': {'usd': '91.40', 'usd_foil': '111.66', 'eur': '69.87', 'tix': '30.29'}}
@pytest.fixture
def mock_external_api():
m = MagicMock(spec=GenericAPI)
m.get_card.return_value = GOOD_RESPONSE
type(m).value = PropertyMock(return_value=GOOD_RESPONSE['prices'])
print(m.value)
return m
class TestCard:
def test_card_price_is_float(self, mock_external_api):
card = Card(name='mox opal', external_api=mock_external_api)
assert isinstance(card.value, float)
错误如下:
=============================================================================================== FAILURES ================================================================================================
___________________________________________________________________________________ TestCard.test_card_price_is_float ____________________________________________________________________________________
self = <test_card.TestCard object at 0x7f3ffdbeffd0>, mock_external_api = <MagicMock spec='ScryfallAPI' id='139912816342632'>
def test_card_price_is_float(self, mock_external_api):
card = Card(name='mox opal', external_api=mock_external_api)
> assert isinstance(card.value, float)
E AssertionError: assert False
E + where False = isinstance(<MagicMock name='mock().value.__getitem__()' id='139912816374616'>, float)
E + where <MagicMock name='mock().value.__getitem__()' id='139912816374616'> = (<class 'collection_app.cards.Card'>, {'name': 'mox opal', 'set_name': None, 'condition': None, 'foil': None, '_value'...ck().value.__getitem__()' id='139912816374616'>, '_external_api': <MagicMock spec='GenericAPI' id='139912816342632'>}).value
collection_app/tests/unit/test_card.py:37: AssertionError
----------------------------------------------------------------------------------------- Captured stdout setup ------------------------------------------------------------------------------------------
{'usd': '91.40', 'usd_foil': '111.66', 'eur': '69.87', 'tix': '30.29'}
=================================================================================== 1 failed, 2 passed in 0.16 seconds ===================================================================================
这是什么错误? 我花了一些时间阅读unittest.mock文档,但我似乎不明白这里缺少什么。