发布时间:2026/9/1 6:11:04
模拟 Anthropic Claude 多模态 API 调用的 Mock 测试类详解 在开发依赖 Anthropic Claude 系列模型如claude-mythos-5、claude-fable-5、claude-opus-5的应用程序时单元测试的编写往往面临两大挑战一是需要真实的 API 密钥和网络连接二是真实调用会产生费用和延迟。为了解决这些问题我们可以设计一个 Mock 测试类它完全模拟官方 Python SDK 的调用接口使得测试代码与生产代码保持一致同时无需任何外部依赖。本文详细介绍了MockAnthropic类的设计与应用它提供了一个与官方 Anthropic Python SDK 完全兼容的模拟客户端支持多模态输入图片、文档和所有常见调用模式。通过使用该 Mock 类开发者可以在单元测试中高效地验证代码逻辑而无需关心网络、密钥或成本问题。未来可根据需要进一步扩展流式响应、异步调用等功能以满足更复杂的测试需求。MockAnthropic 类的设计与实现核心思想是模拟anthropic.Anthropic客户端的行为特别是client.messages.create方法。我们使用SimpleNamespace构建与官方 SDK 返回结构兼容的对象使得测试代码可以直接通过message.content[0].text获取文本而无需任何改动。完整代码fromtypesimportSimpleNamespaceclassMockMessages:模拟 client.messages 对象支持文本、图片和文档附件。SUPPORTED_MODELS{claude-mythos-5,claude-fable-5,claude-opus-5}defcreate(self,model,messages,max_tokens1024,systemNone,**kwargs): 模拟 client.messages.create 调用支持文本、图片和文档输入。 参数与官方 SDK 一致 - model: 模型名称 - messages: 消息列表content 可以是字符串或块列表文本、图片、文档等 - max_tokens: 最大生成 token 数 - system: 系统提示词可选 - **kwargs: 其他参数忽略 返回模拟的 Message 对象结构与官方 SDK 返回一致。 ifmodelnotinself.SUPPORTED_MODELS:raiseValueError(fUnsupported model:{model}. Supported models:{self.SUPPORTED_MODELS})# 提取最后一条用户消息的内容支持字符串和块列表user_textmedia_info[]# 存储图片和文档信息formsginreversed(messages):ifmsg.get(role)user:contentmsg.get(content,)ifisinstance(content,str):user_textcontentelifisinstance(content,list):text_parts[]forblockincontent:block_typeblock.get(type)ifblock_typetext:text_parts.append(block.get(text,))elifblock_typein(image,document):sourceblock.get(source,{})source_typesource.get(type,unknown)media_typesource.get(media_type,unknown)ifblock_typeimage:ifsource_typebase64:datasource.get(data,)media_info.append(f[Image:{media_type}, base64 data length:{len(data)}])elifsource_typeurl:urlsource.get(url,)media_info.append(f[Image URL:{url}, type:{media_type}])else:media_info.append(f[Image:{media_type}, source type:{source_type}])elifblock_typedocument:filenameblock.get(filename,unnamed)ifsource_typebase64:datasource.get(data,)media_info.append(f[Document:{filename},{media_type}, base64 data length:{len(data)}])elifsource_typeurl:urlsource.get(url,)media_info.append(f[Document URL:{filename},{url}, type:{media_type}])else:media_info.append(f[Document:{filename},{media_type}, source type:{source_type}])user_text .join(text_parts)break# 构造模拟回复文本system_prefixf[System:{system}] ifsystemelsemedia_prefix .join(media_info) ifmedia_infoelseresponse_textf{system_prefix}{media_prefix}Mock response from{model}. You said:{user_text}# 根据 max_tokens 粗略截断每 token 按 4 字符估算ifmax_tokensisnotNoneandmax_tokens0:response_textresponse_text[:max_tokens*4]# 构建模拟的 Message 对象与官方 SDK 返回结构兼容mock_content_blockSimpleNamespace(typetext,textresponse_text)mock_usageSimpleNamespace(input_tokenslen(user_text.split())(len(system.split())ifsystemelse0),output_tokenslen(response_text.split()))mock_messageSimpleNamespace(idmsg_mock_12345,typemessage,roleassistant,content[mock_content_block],modelmodel,stop_reasonend_turn,stop_sequenceNone,usagemock_usage)returnmock_messageclassMockAnthropic: 模拟 Anthropic 官方客户端用法与 anthropic.Anthropic 完全一致支持多模态与文档附件。 def__init__(self,api_keyNone,**kwargs):# 可接受 api_key 等参数但全部忽略self.messagesMockMessages()关键设计说明接口一致性MockAnthropic类暴露messages属性其类型为MockMessages提供create方法与官方client.messages.create签名一致。消息解析create方法遍历消息列表提取最后一条用户消息的内容。内容可以是字符串或列表列表中的块类型支持text、image和document。多模态识别对于图片和文档块提取其来源信息base64 数据长度或 URL并生成描述性文本使模拟回复能够反映输入内容。响应构造使用SimpleNamespace构造包含content、usage等属性的对象content是一个列表包含一个typetext的块与真实响应结构一致。错误处理如果传入不支持的模型名称会抛出ValueError模拟真实 SDK 的行为。可扩展性若需要支持流式响应或异步调用可在此基础上添加相应方法。所有类型的调用语句示例以下使用MockAnthropic客户端演示各种可能的调用场景并展示模拟输出结果。1. 非多模态纯文本字符串clientMockAnthropic()messageclient.messages.create(modelclaude-opus-5,max_tokens1024,messages[{role:user,content:Hello, Claude!}])print(message.content[0].text)输出Mock response from claude-opus-5. You said: Hello, Claude!2. 非多模态文本块列表messageclient.messages.create(modelclaude-fable-5,max_tokens512,messages[{role:user,content:[{type:text,text:Tell me a joke.}]}])print(message.content[0].text)输出Mock response from claude-fable-5. You said: Tell me a joke.3. 非多模态带系统提示词messageclient.messages.create(modelclaude-mythos-5,max_tokens1024,systemYou are a helpful assistant.,messages[{role:user,content:What is AI?}])print(message.content[0].text)输出[System: You are a helpful assistant.] Mock response from claude-mythos-5. You said: What is AI?4. 多模态文本 Base64 图片base64_imageiVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkA8AAQUBAScY42YAAAAASUVORK5CYIImessageclient.messages.create(modelclaude-opus-5,max_tokens1024,messages[{role:user,content:[{type:text,text:Whats in this image?},{type:image,source:{type:base64,media_type:image/png,data:base64_image}}]}])print(message.content[0].text)输出[Image: image/png, base64 data length: 68] Mock response from claude-opus-5. You said: Whats in this image?5. 多模态文本 图片 URLmessageclient.messages.create(modelclaude-fable-5,max_tokens512,messages[{role:user,content:[{type:text,text:Describe this picture.},{type:image,source:{type:url,url:https://example.com/image.jpg}}]}])print(message.content[0].text)输出[Image URL: https://example.com/image.jpg, type: unknown] Mock response from claude-fable-5. You said: Describe this picture.6. 多模态文本 Base64 文档PDFbase64_pdfJVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURlY29kZT4CnN0cmVhbQp4nGNgYGJgYGAQZBBhYBSLAGQzB8hgsDAwgATRDAxMgUwGKMDAwMDAwsDAxMDAwMDCwMDAwMDwP0gAISYGBgYGBgYGmessageclient.messages.create(modelclaude-opus-5,max_tokens2048,messages[{role:user,content:[{type:text,text:Summarize this document.},{type:document,source:{type:base64,media_type:application/pdf,data:base64_pdf},filename:report.pdf}]}])print(message.content[0].text)输出[Document: report.pdf, application/pdf, base64 data length: 274] Mock response from claude-opus-5. You said: Summarize this document.7. 多模态文本 文档 URLmessageclient.messages.create(modelclaude-fable-5,max_tokens1024,messages[{role:user,content:[{type:text,text:Extract key points from this file.},{type:document,source:{type:url,url:https://example.com/document.txt},filename:notes.txt}]}])print(message.content[0].text)输出[Document URL: notes.txt, https://example.com/document.txt, type: unknown] Mock response from claude-fable-5. You said: Extract key points from this file.8. 多模态混合文本、图片和文档messageclient.messages.create(modelclaude-opus-5,max_tokens4096,messages[{role:user,content:[{type:text,text:Analyze the image and the document together.},{type:image,source:{type:url,url:https://example.com/chart.png}},{type:document,source:{type:base64,media_type:text/plain,data:SGVsbG8gV29ybGQ},filename:data.txt}]}])print(message.content[0].text)输出[Image URL: https://example.com/chart.png, type: unknown] [Document: data.txt, text/plain, base64 data length: 16] Mock response from claude-opus-5. You said: Analyze the image and the document together.如何在测试中使用 MockAnthropic直接实例化最简单的使用方式是在测试代码中直接创建MockAnthropic实例并将其传递给被测函数通过依赖注入或参数传递。defask_claude(prompt,client):messageclient.messages.create(modelclaude-opus-5,max_tokens1024,messages[{role:user,content:prompt}])returnmessage.content[0].text# 测试代码deftest_ask_claude():mock_clientMockAnthropic()resultask_claude(Hello,mock_client)assertMock responseinresult使用 unittest.mock.patch 替换如果不希望修改生产代码的客户端创建逻辑可以使用patch将anthropic.Anthropic替换为MockAnthropic。fromunittest.mockimportpatchimportanthropicdefask_claude(prompt):clientanthropic.Anthropic()messageclient.messages.create(modelclaude-opus-5,max_tokens1024,messages[{role:user,content:prompt}])returnmessage.content[0].textdeftest_ask_claude_with_patch():withpatch(anthropic.Anthropic,MockAnthropic):resultask_claude(Hello)assertMock responseinresult通过这种方式测试代码与生产代码保持完全一致只需在测试环境中替换客户端类即可。优点与局限性优点零外部依赖无需网络、API 密钥或真实服务测试可离线运行。接口完全兼容调用语法与官方 SDK 相同降低学习成本且测试代码可直接迁移到生产。支持多模态能够处理图片和文档附件覆盖更多真实场景。灵活可定制可以根据需要调整模拟回复的内容或行为例如模拟错误、特定输出等。局限性模拟响应不够真实返回的文本是模板化的无法验证业务逻辑对实际模型输出多样性的处理。缺少高级功能尚未实现流式响应、异步调用、工具调用Tool Use等高级特性但可扩展。token 估算粗略模拟的 token 计数基于简单的字符/单词估算可能与真实 SDK 不一致。

相关新闻

2026/9/1 6:11:04

GEO内容运营每周排期表:周度内容规划

GEO内容运营每周排期表:周度内容规划(可直接套用) 核心结论速览(TL;DR) 做 GEO 内容运营,无计划的零散发布难以积累效果。科学的周度排期能保证内容稳定输出、提升运营效率、均衡平台分布并降低被判定为营销…

2026/9/1 6:06:03

A股产业链关系数据集:实体设计、构建逻辑与投研应用实战

简介:面向金融科技、产业链研究与知识图谱构建场景,该数据集覆盖A股4654家上市公司,整合公司、行业、产品三类核心实体,梳理出公司所属行业、行业上下级隶属、产品上游原材料、下游应用产品、公司主营产品、产品细分小类共6种语义…

2026/9/1 6:06:03

Windows下ZLMediaKit编译部署与GB28181联调实战指南

简介:ZLMediaKit是一套支持RTSP、RTMP、HLS、HTTP-FLV等协议的高性能流媒体服务框架,常用于直播、安防、物联网等场景;这份资源提供Windows系统下已编译好的可运行版本,基于2024年7月的源码构建,并经过播放测试验证。使…

2026/9/1 6:21:04

ReWEIGH技术:大视觉语言模型幻觉问题的Token级校准方案

这次我们来看一个专门解决大视觉语言模型幻觉问题的技术方案:ReWEIGH。这个项目不是新的模型,而是一种校准方法,目标是让模型在回答问题时,更准确地“看到”并“相信”图像中的证据,从而减少胡说八道。大视觉语言模型&…

2026/9/1 6:21:04

揭秘车厢人数统计:为何电子屏显示人数与实际不符?

你有没有遇到过这种情况:走进一个看起来空荡荡的车厢,抬头一看,电子显示屏上却明晃晃地显示着“载客:3人”?明明环顾四周,加上自己也就两个人,那多出来的“第三个人”是谁?是幽灵乘客…

2026/9/1 6:21:04

IMU标定实战:用imu-utils与Allan方差提升VINS/LIO-SAM融合精度

简介:这是一份面向机器人导航、飞行控制及移动设备等场景的IMU传感器标定工具包,适合需要提升惯性测量单元精度的开发者与工程师。压缩包共235个文件,包含txt说明文档、C源程序(h/cpp)、yaml与launch配置文件、sample示…

2026/9/1 6:21:04

26广州卖货小程序商城哪个平台好?先把钱花在哪讲清

引言:同样是卖货商城,报价为什么差这么多?2026年8月,广州白云一家家居用品店准备做卖货小程序。店主黄女士有约150款商品,想做线上下单、到店自提、同城配送和会员券。她收到的报价从198元/年到数万元不等,…

2026/9/1 6:16:04

C++类和对象(四)—— 初始化列表、类型转换、static、友元、内部类、匿名对象与编译器优化

文章目录1. 再探构造函数1.1 初始化列表1.1.1 初始化列表形式1.1.2 初始化列表的本质1.1.3 初始化列表的先后顺序1.1.4 初始化列表的缺省值1.1.5 两个缺省值对比1.1.6 一定要在初始化列表中显式写的变量1.1.7 初始化列表的总结2 类型转换2.1 单参数隐式类型转换2.2 多参数隐式类…

2026/8/31 1:05:20

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/8/31 2:14:20

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/8/31 1:41:28

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/9/1 0:00:42

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/1 0:00:42

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/1 0:00:42

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

2026/9/1 0:00:42

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行&#xff0c;Type-C接口算是典型的“看着简单&#xff0c;做起来全坑”的东西。光引脚就24个&#xff0c;高低速信号、电源、控制线全部塞在一个小小的连接器里&#xff0c;如果PCB布局不做规划&#xff0c;打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/1 0:00:42

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/1 0:00:42

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…