测试读取接口失败后的处理逻辑,桩里已经设置错误码,被测函数却仍然走成功分支;给同一个接口安排“失败一次再成功”,结果两次调用又返回相同数值。这类问题要沿着实际调用检查:程序有没有进入桩、选中了哪个实例、返回后又做了什么处理。Cantata提供Stub、Isolate和Wrapper等调用控制方式,选对控制方式后,才能准确模拟外部依赖。下面采用英文界面的常见名称,具体布局以安装版本为准。
一、Cantata怎样设计桩函数与外部依赖隔离测试
设计桩之前,先划清测试边界。例如测试数据处理模块时,可以模拟设备读取接口;测试设备驱动本身时,就不能把需要验证的驱动逻辑也替换掉。
1、按依赖是否参与构建选择控制方式
①打开测试脚本的【Call Interface Control】,选择目标外部函数,查看当前调用控制类型。
②依赖实现不参与测试构建时,配置Stub;实现仍在构建中、需要替换特定调用时,考虑Isolate或Wrapper替换方式。
Stub用于模拟构建之外的被调对象。Wrapper还可以保留真实调用,在调用前后检查数据,因此“已经生成Wrapper”不等于“已经隔离真实依赖”。
2、为不同场景建立调用实例
①在【Call Interface Control】选中目标函数,进入【Instances】。
②点击新增实例的【+】,分别建立成功、失败等实例,并填写便于辨认的名称。
③选择各实例,在【Return Value】填写对应返回值。
返回值应遵守接口约定。比如返回零代表成功、负数代表失败,就不要仅用任意非零数模拟故障。指针或引用返回值还需要有效对象,不能只填一个看似可用的地址。
3、安排当前用例使用的实例
“第一次超时、第二次成功”需要两个调用行为,并按顺序交给当前用例。
①进入【Test Cases】,选择目标用例,打开【Expected Call Sequence】。
②从调用控制列表中选择相应实例,按预期顺序加入调用序列。
③核对实例名称和出现次数,保存测试脚本。
只创建实例而没有让用例选择它,不能保证本次调用会使用该实例中的返回值。
4、补齐输出参数和接口检查
①返回【Call Interface Control】→【Instances】,选中准备使用的实例。
②在【Basic】中设置可用的参数检查及数据操作;复杂模拟逻辑进入【Advanced】或脚本编辑区补充。
③在【Test Cases】中配置被测函数的预期结果。
例如读取接口通过返回值表示状态、通过指针交付数据,两部分都要模拟。否则即使返回成功,被测函数仍可能读到旧数据或未初始化内容。
二、Cantata桩函数返回值未按测试预期生效如何定位
先核实桩是否被调用,再核实调用实例。直接反复修改返回值,往往绕不开真正的问题。
1、检查真实调用与桩是否对应
①在【Call Interface Control】选择目标函数,对照生成脚本中的完整函数签名。
②检查【Test Cases】→【Expected Call Sequence】,确认当前用例确实安排了该调用。
③查看执行结果中的调用顺序、参数检查及未预期调用信息。
④对函数指针、C++重载或虚函数调用,继续核对实际指向的实现。
同名函数可能具有不同参数或命名空间,函数指针也可能在初始化时换了目标。链接成功只说明符号得到了解决,不能证明运行时进入了你修改的那个桩。
2、检查实例和Wrapper执行方式
①在【Instances】选择当前用例引用的实例,重新核对【Return Value】。
②打开【Expected Call Sequence】,检查重试、循环或前置操作是否提前消耗了某次调用。
③使用Wrapper时,在脚本编辑区核对BEFORE之后进入的是原函数还是REPLACE段。
Cantata自动生成的Wrapper通常采用BEFORE-AFTER配对,真实函数仍会运行。若要完全模拟,应采用对应的替换行为;只修改某个未执行的REPLACE实例,当前用例当然不会变化。
3、检查返回后的处理及构建结果
①在【Instances】→【Advanced】或脚本中,检查实际返回语句及后续数据修改。
②回到【Test Cases】,核对预期结果是否针对被测函数最终输出,而非直接照抄依赖返回码。
③保存修改,通过【Project】→【Clean...】清理测试工程,再重新构建并执行。
依赖返回的错误码可能被被测函数转换成另一种状态,也可能触发重试后被覆盖。若接口返回类型是无符号整数,负数的实际含义也会改变。此时应检查接口类型和处理逻辑,而不能仅凭最终返回值认定桩未生效。
三、Cantata隔离测试完成后如何复核
用例通过以后,还要确认通过的原因符合测试目的。桩配置过于宽松,可能让错误参数或多余调用悄悄通过。
1、检查参数与调用次数
①在【Call Interface Control】→【Instances】补充关键参数检查,例如设备编号、缓冲区长度和请求标志。
②进入【Test Cases】→【Expected Call Sequence】,核对正常路径与重试路径的调用次数和顺序。
③分别执行成功、失败和重试用例,检查调用验证结果。
错误处理测试还应关注“没有发生什么”。读取失败后不应继续写入设备时,需要检查后续调用是否意外出现。
2、检查用例间的状态独立性
①在【Test Cases】依次选择相关用例,检查各自的初始化数据和预期结果。
②在【Instances】中检查模拟逻辑使用的计数器、缓存及全局变量,补齐每个用例所需的初值。
③保存脚本后,分别单独运行用例,再运行整组测试。
单独通过、成组失败,值得优先检查共享状态。前一用例留下的计数或输出缓冲区,可能改变下一用例的实例行为。
3、保留真实依赖的集成验证
①在【Call Interface Control】检查哪些接口仍由Stub模拟,哪些Wrapper保留真实调用。
②在【Test Cases】中选择集成场景,配置真实返回值、参数及调用顺序的检查。
隔离测试可以稳定制造超时、内存不足等条件,但模拟结果不能代替真实驱动、第三方库或硬件接口的兼容性验证。两类测试各自保留,证据才更完整。
总结
桩函数承载的是团队对外部接口的理解,接口约定变了,测试中的模拟也需要跟着调整。Cantata的调用实例和Wrapper能帮助构造难以稳定复现的异常条件,让错误处理得到更具体的验证。长期维护时,为模拟行为注明接口依据和适用场景,比堆积大量默认返回值更有用,也方便接手人员判断测试覆盖了什么。希望这些内容能帮助大家查清桩返回值异常,减少无效重跑。如需了解单元测试及相关软件应用,欢迎沟通咨询。