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

.NET Core 2中模拟Hangfire RecurringJob依赖及注入抽象咨询

Answer

Great question! Let’s tackle this directly: out of the box, Hangfire does not provide a built-in injectable abstraction specifically for RecurringJob—as you’ve noticed, the only core abstraction is IBackgroundJobClient, which doesn’t cover recurring task scheduling.

The good news is this is a common pain point for testing, and there’s a clean, community-standard workaround: wrap the static RecurringJob class in your own injectable abstraction. Here’s how to do it step-by-step:

1. Define a Custom Abstraction

Create an interface that mirrors the RecurringJob methods you need (you can add more as required):

public interface IRecurringJobScheduler
{
    void AddOrUpdate<T>(
        string jobId,
        Expression<Func<T, Task>> methodCall,
        string cronExpression,
        TimeZoneInfo timeZone = null);

    void RemoveIfExists(string jobId);
    // Add other methods like Trigger, Update, etc., as needed
}

2. Implement the Wrapper

Create a concrete implementation that delegates to Hangfire’s static RecurringJob class:

public class HangfireRecurringJobScheduler : IRecurringJobScheduler
{
    public void AddOrUpdate<T>(string jobId, Expression<Func<T, Task>> methodCall, string cronExpression, TimeZoneInfo timeZone = null)
    {
        RecurringJob.AddOrUpdate(jobId, methodCall, cronExpression, timeZone ?? TimeZoneInfo.Local);
    }

    public void RemoveIfExists(string jobId)
    {
        RecurringJob.RemoveIfExists(jobId);
    }
}

3. Register the Abstraction in DI

In your .NET Core 2 Startup.cs, add the wrapper to the service collection:

public void ConfigureServices(IServiceCollection services)
{
    // ... other services
    services.AddScoped<IRecurringJobScheduler, HangfireRecurringJobScheduler>();
}

4. Use the Abstraction in Your Code

Instead of calling RecurringJob directly, inject IRecurringJobScheduler into your services:

public class MyScheduledJobService
{
    private readonly IRecurringJobScheduler _jobScheduler;

    public MyScheduledJobService(IRecurringJobScheduler jobScheduler)
    {
        _jobScheduler = jobScheduler;
    }

    public void SetupDailyCleanupJob()
    {
        _jobScheduler.AddOrUpdate<CleanupJob>(
            "daily-cleanup-job",
            job => job.RunCleanup(),
            "0 0 * * *"); // Daily at midnight
    }
}

5. Unit Testing with Mocks

Now you can easily mock the IRecurringJobScheduler to verify that jobs are being added correctly (using a library like Moq):

[TestClass]
public class MyScheduledJobServiceTests
{
    [TestMethod]
    public void SetupDailyCleanupJob_Should_AddRecurringJob()
    {
        // Arrange
        var mockScheduler = new Mock<IRecurringJobScheduler>();
        var service = new MyScheduledJobService(mockScheduler.Object);

        // Act
        service.SetupDailyCleanupJob();

        // Assert
        mockScheduler.Verify(s => s.AddOrUpdate<CleanupJob>(
            "daily-cleanup-job",
            It.IsAny<Expression<Func<CleanupJob, Task>>>(),
            "0 0 * * *",
            It.IsAny<TimeZoneInfo>()), Times.Once);
    }
}

This approach keeps your code decoupled from Hangfire’s static implementation, making it testable while retaining all the power of Hangfire’s recurring job functionality.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:51:56