同时使用@mock_sqs与@pytest.mark.asyncio出现CredentialsNotFound错误如何解决
问题根源
- 装饰器执行顺序错误:当前写法下
@mock_sqs先于@pytest.mark.asyncio生效,异步测试的执行上下文没有被moto的mock环境完整包裹,mock状态没有覆盖到测试运行阶段,导致请求直接落到真实AWS环境。 - moto默认同步装饰器对异步测试的上下文兼容性差:moto的mock状态默认存储在线程本地存储中,异步协程的切换逻辑容易脱离mock的作用域。
解决方案
方案1(最稳妥,无兼容问题):用上下文管理器替代装饰器
直接在测试函数内部手动开启mock_sqs上下文,确保所有SQS相关操作都在mock作用域内执行:
import pytest from moto import mock_sqs @pytest.mark.asyncio async def test_foo(monkeypatch): # 手动开启mock上下文 with mock_sqs(): client = setup_mock_client() # 创建AWS客户端 client.send_message(...) # mock生效,不会请求真实服务 # 剩余测试逻辑
方案2:调整装饰器顺序
将@mock_sqs放在@pytest.mark.asyncio外层,确保mock包裹整个异步测试的执行流程,同时将测试函数声明为异步函数:
from moto import mock_sqs import pytest @mock_sqs @pytest.mark.asyncio async def test_foo(monkeypatch): client = setup_mock_client() client.send_message(...)
额外注意事项
- 创建SQS客户端时必须填写合法的region参数(如
us-east-1),moto即使是mock模式也需要校验合法region值。 - 如果使用异步AWS SDK(aiobotocore、aioboto3),请升级moto到3.x及以上版本,旧版本对异步SDK的兼容存在缺陷。
- 可以在创建客户端时硬编码假密钥参数(
aws_access_key_id='fake', aws_secret_access_key='fake'),避免mock失效时意外请求真实AWS服务,同时也能快速定位mock是否生效。
内容的提问来源于stack exchange,提问作者Stack Overflow
相关产品推荐
相关产品推荐

