在MSTest中验证Hangfire的BackgroundJob.Delete单元测试方案
在MSTest中验证Hangfire Delete扩展方法的调用
因为扩展方法本质是静态方法,无法直接通过Mock框架(比如Moq)进行验证,核心思路是验证扩展方法内部实际调用的实例方法,结合Hangfire的具体实现来处理:
1. 明确Hangfire Delete扩展方法的底层逻辑
你调用的BackgroundJobClient.Delete(jobId)扩展方法,本质是调用IBackgroundJobClient接口的实例方法:
client.Delete(new DeleteJobRequest { JobId = jobId });
所以不需要直接验证扩展方法,转而验证这个实例方法的调用即可。
2. 调整代码的依赖方式
确保你的业务类通过依赖注入获取IBackgroundJobClient和JobStorage,而不是直接实例化或使用静态属性(比如JobStorage.Current),这样才能在测试中替换为Mock对象:
public class JobService { private readonly IBackgroundJobClient _jobClient; private readonly JobStorage _jobStorage; // 构造注入依赖 public JobService(IBackgroundJobClient jobClient, JobStorage jobStorage) { _jobClient = jobClient; _jobStorage = jobStorage; } public void CancelScheduledJob(Guid targetJobId) { var monitoringApi = _jobStorage.GetMonitoringApi(); var scheduledJobs = monitoringApi.ScheduledJobs(); var targetJob = scheduledJobs.FirstOrDefault(job => job.Job.Arguments.Contains(targetJobId.ToString())); if (targetJob != null) { _jobClient.Delete(targetJob.JobId); // 这里的Delete是扩展方法 } } }
3. 编写MSTest测试用例
使用Moq(或其他Mock框架)MockIBackgroundJobClient、JobStorage和IMonitoringApi,验证实例方法的调用:
[TestClass] public class JobServiceTests { [TestMethod] public void CancelScheduledJob_MatchingJobExists_CallsDelete() { // Arrange var targetGuid = Guid.NewGuid(); var testJobId = "test-scheduled-job-001"; // Mock MonitoringApi,返回包含目标Guid的作业 var mockMonitoringApi = new Mock<IMonitoringApi>(); mockMonitoringApi.Setup(api => api.ScheduledJobs()) .Returns(new List<ScheduledJobDto> { new ScheduledJobDto { JobId = testJobId, Job = new JobDto { Arguments = $"[\"{targetGuid.ToString()}\"]" } } }); // Mock JobStorage,返回上面的MonitoringApi var mockJobStorage = new Mock<JobStorage>(); mockJobStorage.Setup(storage => storage.GetMonitoringApi()) .Returns(mockMonitoringApi.Object); // Mock IBackgroundJobClient,用于验证Delete调用 var mockJobClient = new Mock<IBackgroundJobClient>(); // 初始化被测试类 var jobService = new JobService(mockJobClient.Object, mockJobStorage.Object); // Act jobService.CancelScheduledJob(targetGuid); // Assert:验证IBackgroundJobClient的Delete实例方法是否被调用,且参数正确 mockJobClient.Verify(client => client.Delete( It.Is<DeleteJobRequest>(req => req.JobId == testJobId)), Times.Once); } }
特殊情况:如果使用静态的BackgroundJob.Delete(jobId)
如果你的代码调用的是静态扩展方法BackgroundJob.Delete(jobId),它内部会调用JobStorage.Current.GetConnection().DeleteJob(jobId)。这种情况下需要:
- Mock
IStorageConnection并验证DeleteJob方法的调用 - 通过反射替换
JobStorage.Current为Mock对象(测试后记得恢复原实例,避免影响其他测试)
不过更推荐使用依赖注入IBackgroundJobClient的方式,测试逻辑更清晰,也符合依赖倒置原则。
内容的提问来源于stack exchange,提问作者B.Quaink
相关产品推荐
相关产品推荐

