如何用Delphi和TestInsight测试含匿名方法的程序并解决同步异常?
解决TestInsight测试异步REST请求时的CheckSynchronize异常问题
问题根源
你在异步回调的匿名方法中直接执行TestInsight的Assert方法,而TestInsight的断言逻辑依赖测试主线程的上下文。即便回调做了同步处理,若同步目标线程(比如UI线程)与测试线程不一致,就会触发CheckSynchronize异常。
解决方案核心思路
- 不在异步回调中执行断言,仅收集结果到测试主线程可见的变量中
- 用
TEvent替代循环+Application.ProcessMessages的等待方式,避免消息循环带来的线程冲突
修改后的测试代码
procedure Shows.GetAgenda; var CompletedEvent: TEvent; LocalStatusCode: Integer; LocalRecordCount: Integer; LocalErrorMessage: string; begin CompletedEvent := TEvent.Create(nil, True, False, ''); try // 初始化结果变量 LocalStatusCode := -1; LocalRecordCount := 0; LocalErrorMessage := ''; DmShows.LoadShows(120, procedure (ServerResult: TServerResult) begin try // 仅收集结果,不执行断言 LocalStatusCode := ServerResult.StatusCode; LocalErrorMessage := ServerResult.Message; LocalRecordCount := DmShows.TableShows.RecordCount; finally // 触发事件通知主线程任务完成 CompletedEvent.SetEvent; end; end); // 等待异步操作完成,设置5秒超时 if CompletedEvent.WaitFor(5000) <> wrSignaled then begin Assert.Fail('REST请求超时'); end; // 回到测试主线程执行断言 Assert.IsTrue(LocalStatusCode = 200, LocalErrorMessage); Assert.IsTrue(LocalRecordCount > 0, 'No shows found for testing.'); finally CompletedEvent.Free; end; end;
关键改动说明
- 用TEvent实现安全等待:替代原有的循环+
Application.ProcessMessages,避免在测试环境中因消息循环引发的线程同步问题,同时支持超时判断,防止测试无限挂起。 - 分离结果收集与断言逻辑:回调仅负责把接口返回值、数据集记录数等结果保存到主线程变量,所有断言操作移到测试主线程执行,确保在TestInsight期望的线程上下文运行。
- 添加超时处理:通过
WaitFor(5000)设置5秒超时,避免因接口无响应导致测试卡住。
内容的提问来源于stack exchange,提问作者Edward
相关产品推荐
相关产品推荐

