Pytest Mock链式调用断言失败:Mock对象与字符串对比错误
问题:unittest.mock链式调用Mock返回值不生效
测试场景代码
from simple_salesforce import Salesforce from unittest.mock import Mock class SFClient: def __init__(self, sf_client: Salesforce): self._simple_sf_client = sf_client def bulk2(self, query: str, path: str, max_records: int) -> list[dict]: return self._simple_sf_client.bulk2.Account.download( query=query, path=path, max_records=max_records ) def test_client_bulk2(): mock_sf = Mock() config = {'bulk2.return_value.Account.return_value.download.return_value': 'test'} mock_sf.configure_mock(**config) client = SFClient(sf_client=mock_sf) assert client.bulk2('query', 'path', 1) == 'test' assert False
错误日志
运行pytest后报错:
$ poetry run pytest F [100%] ======================================================================================================================================================= FAILURES ======================================================================================================================================================= __________________________________________________________________________________________________________________________________________________ test_client_bulk2 ___________________________________________________________________________________________________________________________________________________ def test_client_bulk2(): mock_sf = Mock() config = {'bulk2.return_value.Account.return_value.download.return_value': 'test'} mock_sf.configure_mock(**config) client = SFClient(sf_client=mock_sf) > assert client.bulk2('query', 'path', 1) == 'test' E AssertionError: assert <Mock name='mock.bulk2.Account.download()' id='140589080832208'> == 'test' E + where <Mock name='mock.bulk2.Account.download()' id='140589080832208'> = <bound method SFClient.bulk2 of <tests.test_salesforce.SFClient object at 0x7fdd73acdd90>>('query', 'path', 1) E + where <bound method SFClient.bulk2 of <tests.test_salesforce.SFClient object at 0x7fdd73acdd90>> = <tests.test_salesforce.SFClient object at 0x7fdd73acdd90>.bulk2 tests/test_salesforce.py:27: AssertionError =================================================================================================================================================== warnings summary =================================================================================================================================================== ../../.cache/pypoetry/virtualenvs/salesforce-archivist-n3oqdCBe-py3.11/lib/python3.11/site-packages/zeep/utils.py:1 /home/piotrek/.cache/pypoetry/virtualenvs/salesforce-archivist-n3oqdCBe-py3.11/lib/python3.11/site-packages/zeep/utils.py:1: DeprecationWarning: 'cgi' is deprecated and slated for removal in Python 3.13 import cgi -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html =============================================================================================================================================== short test summary info ================================================================================================================================================ FAILED tests/test_salesforce.py::test_client_bulk2 - AssertionError: assert <Mock name='mock.bulk2.Account.download()' id='140589080832208'> == 'test' 1 failed, 1 warning in 0.19s
编辑后的尝试
尝试修改断言为assert client.bulk2('query', 'path', 1).return_value == 'test',仍然失败:
$ poetry run pytest F [100%] ======================================================================================================================================================= FAILURES ======================================================================================================================================================= __________________________________________________________________________________________________________________________________________________ test_client_bulk2 ___________________________________________________________________________________________________________________________________________________ def test_client_bulk2(): mock_sf = Mock() config = {'bulk2.return_value.Account.return_value.download.return_value': 'test'} mock_sf.configure_mock(**config) client = SFClient(sf_client=mock_sf) > assert client.bulk2('query', 'path', 1).return_value == 'test' E AssertionError: assert <Mock name='mock.bulk2.Account.download()()' id='140508290106704'> == 'test' E + where <Mock name='mock.bulk2.Account.download()()' id='140508290106704'> = <Mock name='mock.bulk2.Account.download()' id='140508282777104'>.return_value E + where <Mock name='mock.bulk2.Account.download()' id='140508282777104'> = <bound method SFClient.bulk2 of <tests.test_salesforce.SFClient object at 0x7fcaa2b95150>>('query', 'path', 1) E + where <bound method SFClient.bulk2 of <tests.test_salesforce.SFClient object at 0x7fcaa2b95150>> = <tests.test_salesforce.SFClient object at 0x7fcaa2b95150>.bulk2 tests/test_salesforce.py:27: AssertionError =================================================================================================================================================== warnings summary =================================================================================================================================================== ../../.cache/pypoetry/virtualenvs/salesforce-archivist-n3oqdCBe-py3.11/lib/python3.11/site-packages/zeep/utils.py:1 /home/piotrek/.cache/pypoetry/virtualenvs/salesforce-archivist-n3oqdCBe-py3.11/lib/python3.11/site-packages/zeep/utils.py:1: DeprecationWarning: 'cgi' is deprecated and slated for removal in Python 3.13 import cgi -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html =============================================================================================================================================== short test summary info ================================================================================================================================================ FAILED tests/test_salesforce.py::test_client_bulk2 - AssertionError: assert <Mock name='mock.bulk2.Account.download()()' id='140508290106704'> == 'test' 1 failed, 1 warning in 0.19s
原因与解决方案
问题根源
原代码中self._simple_sf_client.bulk2是直接访问属性(没有调用方法,即无bulk2()),但配置mock时错误地给bulk2添加了.return_value,导致mock结构与实际调用链不匹配。
实际调用链是:mock_sf.bulk2.Account.download(...),而你的配置是给mock_sf.bulk2()(方法调用)的返回值设置了Account属性,和实际调用的mock_sf.bulk2属性完全不是同一个对象。
修正后的测试代码
将mock配置中的bulk2.return_value改为bulk2,去掉多余的.return_value:
def test_client_bulk2(): mock_sf = Mock() # 修正配置:去掉bulk2后的.return_value config = {'bulk2.Account.download.return_value': 'test'} mock_sf.configure_mock(**config) client = SFClient(sf_client=mock_sf) assert client.bulk2('query', 'path', 1) == 'test' # 删除assert False,让测试正常通过
验证
修改后运行pytest,断言会成功通过,因为现在mock的结构与实际调用链完全匹配:mock_sf.bulk2是一个Mock对象,它的Account属性的download方法返回值被设置为'test',和原代码的调用逻辑一致。
内容的提问来源于stack exchange,提问作者piotrekkr
相关产品推荐
相关产品推荐

