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

并行测试中Quartz调度器重复创建引发的已存在异常问题

Quartz调度器并行测试重复创建问题解决方案

问题描述

运行并行测试时遇到错误:
Quartz.SchedulerException : Scheduler with name 'DefaultQuartzScheduler' already exists

原因是每个测试都会创建独立的Web应用工厂实例,导致Quartz调度器被重复初始化。目前通过给命名空间添加[assembly: CollectionBehavior(DisableTestParallelization = true)]可以解决,但这是临时方案,而且ASP.NET依赖注入中无法直接传递Scheduler实例。

当前DI配置代码:

services.AddQuartz(options =>
{
    options.UseMicrosoftDependencyInjectionJobFactory();
});

services.AddQuartzHostedService(options =>
{
    options.WaitForJobsToComplete = true;
});

可行解决方案

1. 为每个测试实例生成唯一调度器名称

修改DI配置,支持动态指定调度器名称,测试时为每个Web应用工厂分配唯一标识:

services.AddQuartz((provider, options) =>
{
    options.UseMicrosoftDependencyInjectionJobFactory();
    // 从配置获取名称,测试时注入唯一值
    var schedulerName = provider.GetRequiredService<IConfiguration>()["Quartz:Scheduler:Name"] ?? "DefaultQuartzScheduler";
    options.SchedulerName = schedulerName;
});

测试代码中覆盖配置:

var factory = new WebApplicationFactory<Program>().WithWebHostBuilder(builder =>
{
    builder.ConfigureAppConfiguration((context, config) =>
    {
        config.AddInMemoryCollection(new Dictionary<string, string>
        {
            ["Quartz:Scheduler:Name"] = $"TestScheduler_{Guid.NewGuid()}"
        });
    });
});

2. 用测试集合隔离调度器实例

把依赖Quartz的测试归到同一个集合,同一集合内的测试串行执行,不影响其他测试并行:

[CollectionDefinition("QuartzTests")]
public class QuartzTestCollection : ICollectionFixture<WebApplicationFactory<Program>>
{
    // 仅用于标记集合,无需实现方法
}

在测试类上标记集合:

[Collection("QuartzTests")]
public class MyQuartzTests
{
    // 测试逻辑
}

3. 测试时禁用Quartz Hosted Service

如果测试不需要调度器运行,可以直接移除或替换Quartz的Hosted Service:

var factory = new WebApplicationFactory<Program>().WithWebHostBuilder(builder =>
{
    builder.ConfigureServices(services =>
    {
        var quartzHostedService = services.SingleOrDefault(d => 
            d.ServiceType == typeof(IHostedService) && 
            d.ImplementationType == typeof(QuartzHostedService));
        if (quartzHostedService != null)
        {
            services.Remove(quartzHostedService);
        }
        // 可选:替换为模拟的Hosted Service
        services.AddSingleton<IHostedService, MockHostedService>();
    });
});

内容的提问来源于stack exchange,提问作者D. Nizio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:42:58