Unit Testing Scheduler in the FUTURE C#

2.1k views Asked by At

I'm using quartz.NET inside a scheduler project (class library) on my application, this is because i want the other projects to be agnostic of the actual implementation. In the future, if i want to change quartz for Castle Scheduler or Windows Scheduler or wathever... i will have the flexibility to change it.

I need to unit test weekly triggers on my Quartz.NET project, I started researching and found out what at the moment seemed to be a cool solution MOLES this extension basically allows me to change the DateTime.Now and go TO THE FUTURE!!

In this case, one week from now, when the trigger is scheduled to fire, but after waiting a little time found with sadness that my triggers were not being activated, even when changing the time and Thread.Sleeping a couple of minutes...

The reason that I want to go to the future is because within the application I'm using different methods/triggers for each kind of request E.G. Weekly, Weekly with recurrence, Monthly, Yearly

Has anyone else Unit Tested this kind of scenario?

Is there something that i'm passing by?

Is it possible with MOLES?

2

There are 2 answers

2
nulltoken On

How about implementing something like

public interface IClock
{
    DateTime Now { get; }
}

public class FakeClock : IClock
{
    DateTime Now { get; set; }
}

public class SystemClock : IClock
{
    DateTime Now { get { return DateTime.Now; } }
}

As you develop a facade, you could make your code depend on IClock, by replacing every call to DateTime.Now to IClock.Now.

The IClock dependency could be passed as a constructor parameter or directly to each method that requires it.

Then, your production code would use a SystemClock instance and your tests could rely on the FakeClock type to manipulatime the time and verify that some operation do occur at expected instant.

That kind of design (Inversion of Control) greatly benefits from working with a Dependency Injection container such as Castle Windsor, StructureMap, AutoFac, ...

Note: For further reference, similar implementation proposal in discussed in this post.

0
Simon Stender Boisen On

I havn't tested this yet but when you tried Moles did you change DateTimeOffset or DateTime? Quartz.Net uses DateTimeOffset.UtcNow:

https://fisheye3.atlassian.com/browse/quartznet/src/Quartz/SystemTime.cs?hb=true

I think you should be able to do this without using moles though I havn't tested this either, just write

SystemTime.UtcNow = () => new DateTimeOffset(DateTime.Now.AddDays(5)).UtcNow

when you want to be five days into the future :)

Please note that the SystemTime-functionality require that you build Quartz from source, you can get the source at github:

https://github.com/lahma/quartznet