keycad
keycad

Reputation: 113

Unit test IBackgroundJobClient.Schedule

I am using Hangfire to schedule some jobs. All my jobs have a schedule date, so I'm using Schedule static extension method

public static string Schedule([NotNull] this IBackgroundJobClient client, [InstantHandle][NotNull] Expression<Action> methodCall, DateTimeOffset enqueueAt);

I want to unit test my methods, so that I can check that Hangfire is actually being triggered.

To do so, I've followed Hangfire's documentation on unit testing (https://docs.hangfire.io/en/latest/background-methods/writing-unit-tests.html) which suggests mocking IBackgroundJobClient and verifying on the only public Create method it has:

string Create([NotNull] Job job, [NotNull] IState state);

But I can see that for Schedule invocations, this is not being called, another overload that is not public is being called instead, so I get the following error:

Message: Moq.MockException : 
Expected invocation on the mock at least once, but was never performed: x => x.Create(It.IsAny<job>(), It.IsAny<enqueuedstate>())
No setups configured.

Performed invocations: 
IBackgroundJobClient.Create(JobService.TaskFunction, ScheduledState)

Nevertheless, I've made an attempt with Enqueue method, and that seems to work with the mock. But I need to use Schedule.

Another option would be to assert on the overload it is actually calling

public static string Create([NotNull] this IBackgroundJobClient client, [InstantHandle][NotNull] Expression<Action> methodCall, [NotNull] IState state);

But since it's an extension method, that's not a valid approach for Moq.

Message: System.NotSupportedException : Invalid verify on an extension method: x => x.Create(It.IsAny<Expression<Action>>(), It.IsAny<EnqueuedState>())

So how can I unit test Hangfire for Schedule method?

Upvotes: 3

Views: 3388

Answers (1)

Johnny
Johnny

Reputation: 9519

The example you refer to uses different extension method which at the end calls different IBackgroundJobClient method, github. The following method has been invoked:

client.Create(Expression<Action> methodCall, new EnqueuedState());

It perfectly fits the Verify within the example.


On the other hand, your are calling Schedule method, github. Schedule method at the end invokes the following:

client.Create(Expression<Action> methodCall, new ScheduledState(enqueueAt.UtcDateTime))

Which is also an expression method, so you need to dive deeper one more level where actual interface method has been called:

string Create([NotNull] Job job, [NotNull] IState state);

As you can see from the error itself your expectation doesn't match with the actual invocation:

Performed invocations: 
IBackgroundJobClient.Create(JobService.TaskFunction, ScheduledState)

Your assert should be something like this:

// Assert
client.Verify(x => x.Create(
    It.IsAny<Job>(), //you could as in example check actual method name
    It.IsAny<IState>())); //you could check actual offset

Upvotes: 5

Related Questions