.NET Core 2中模拟Hangfire RecurringJob依赖及注入抽象咨询
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

