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

如何测试不改变Saga状态的定时Schedule事件是否正常触发

解决Saga定时事件测试等待问题

你遇到的断言失败问题本质是:调用AdvanceSystemTime只会推进测试用的时间源,触发调度器把待执行的定时消息投递到总线管道,但不会等待消息消费逻辑跑完。你直接执行断言的时候,发邮件的逻辑可能还没执行到,自然拿不到正确的计数,不需要修改Saga业务代码,下面几个方案都能解决:

方案1:直接等待定时事件消息被消费

所有MassTransit调度实现(内置延迟、Quartz、Hangfire)触发定时事件时,本质都是向Saga投递一条对应的事件消息,你不需要依赖Saga状态变更,直接通过测试工具等待这条消息被消费完成即可:

await AdvanceSystemTime(TimeSpan.FromDays(3.5));

// 替换为你自己定义的定时提醒事件类型
var reminderConsumed = await TestHarness.Consumed
    .SelectAsync<FormRequestReminderEvent>(msg => msg.CorrelationId == formRequest.CorrelationId)
    .FirstOrDefault();

Assert.IsNotNull(reminderConsumed, "定时提醒事件未被Saga消费");
NotificationGatewayMock.ThenDirectNotificationsWasSent(2);

如果你是用Schedule<T, TMessage>语法定义的Saga定时事件,这里的消息类型就填你当时配置Schedule时传入的事件类型即可,框架会自动关联CorrelationId到对应Saga实例。

方案2:等待测试总线空闲

不想硬编码指定事件类型的话,直接等测试总线把所有待处理的消息都消费完再断言就行:

await AdvanceSystemTime(TimeSpan.FromDays(3.5));

// 等待总线所有入队消息处理完成、进入空闲状态
await TestHarness.InactivityTask;
// 极端情况加个50毫秒的短裕度就行,不需要长等待
await Task.Delay(50, TestContext.Current.CancellationToken);

NotificationGatewayMock.ThenDirectNotificationsWasSent(2);

这个方法对业务代码零侵入,只要你的定时事件逻辑是走MassTransit消费管道执行的,就能被正确等待到。

方案3:Mock层加信号等待(稳定性最高)

如果想完全不依赖测试框架的内部实现,可以在通知网关的Mock里加完成信号,通知发送数量达到预期时直接触发信号,测试代码等待信号即可,还可以配置超时避免测试卡死:

// 测试初始化阶段配置Mock和信号源
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
NotificationGatewayMock
    .Setup(g => g.Send(It.IsAny<EmailNotification>()))
    .Callback(() =>
    {
        if (NotificationGatewayMock.SendCount == 2)
            tcs.TrySetResult();
    });

// 快进时间后等待信号,最多等3秒就超时判失败
await tcs.Task.WaitAsync(TimeSpan.FromSeconds(3), TestContext.Current.CancellationToken);

NotificationGatewayMock.ThenDirectNotificationsWasSent(2);

这个方案不受MassTransit版本变化影响,CI环境负载高的时候也不会出现偶发失败。

避坑提醒

不要直接用长固定等待比如Task.Delay(1000)硬等,既会拖慢测试执行速度,负载高的时候还是会出现偶发失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 03:06:38