You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无需重新调用获取未Mock函数的原始return_value?

问题:Mock异步函数时如何获取原始返回值用于断言?

我查阅了相关文档,但没找到怎么访问foo_hello函数的原始/预期/未修改的return_value来做断言。目前想到的最优方案是从call_args里取参数重新调用函数。用side_effect的时候确实会调用foo_hello,但查看foo.return_value只能拿到AsyncMock对象。有没有不用重新调用函数就能获取返回值的方法?

另外想问:Mock函数/对象的return_value能不能和未Mock时函数运行的预期返回值一致?我试过设置wraps为foo_hello,效果和side_effect差不多。

示例代码:

from unittest.mock import patch
import pytest


async def foo_hello(x, y):
    return {f"hello {z}":f"world {y}"}  # 注:原代码中z应为x,属于笔误


@pytest.mark.asyncio
async def test(client: AsyncClient):
    payload = {"foo": "bar", "hello": "world"}
    with patch(
        "module.foo_hello",side_effect=foo_hello
    ) as foo,
        patch(
        "module.create_pool",
        return_value=MockArqRedis(),
    ):
        # handler function calls foo_hello down stream
        response = await handler_function(
            request=payload,
            user_id=user.id,
        )
    
        foo.assert_called_once_with(
            x=some_value,
            y=some_value,
        )

        parameters = foo.call_args[1]
        foo_return: dict = await foo(**parameters)
     
     assert "some_value" in foo_return

解决方案

1. 自定义side_effect捕获返回值

不用重新调用函数,直接在side_effect里把原始函数的返回值存下来,后续直接使用即可:

from unittest.mock import patch
import pytest

async def foo_hello(x, y):
    return {f"hello {x}": f"world {y}"}  # 修正原代码的z笔误

@pytest.mark.asyncio
async def test(client: AsyncClient):
    payload = {"foo": "bar", "hello": "world"}
    # 用于存储原始函数的返回值
    captured_return = None

    async def capture_result(*args, **kwargs):
        nonlocal captured_return
        result = await foo_hello(*args, **kwargs)
        captured_return = result
        return result

    with patch(
        "module.foo_hello", side_effect=capture_result
    ) as foo, patch(
        "module.create_pool", return_value=MockArqRedis()
    ):
        await handler_function(request=payload, user_id=user.id)
        
        foo.assert_called_once_with(x=some_value, y=some_value)
        
        # 直接用捕获的返回值做断言
        assert "some_value" in captured_return

2. 关于return_value与原始返回值同步的问题

Mock对象的return_value是预设的固定返回值,和side_effect/wraps的动态调用逻辑是分开的——即使你用wraps或者side_effect指向原始函数,return_value也不会自动同步原始函数的返回结果。

如果硬要让return_value等于原始返回值,只能像上面那样手动捕获后赋值,但完全没必要,直接用捕获返回值的方式更直接高效。


内容的提问来源于stack exchange,提问作者Hyperion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:25:15