The sample code used in this post can be found here.
For either scheduled WebJob instance or on-demand WebJob instance, it’s just a console application that we’re not dealing with. However, when we look at the continuous running WebJob instance, it will be a different story. Let’s have a look at the basic WebJob code.
This is the main WebJob host entry. Within the
Main() method, it creates the
JobHostConfiguration instance and
JobHost instance for a WebJob application that is continuously running. This is the actual WebJob function.
As we can see, it has the
static modifier, which make us hard to test. We can use the service locator pattern for this
static method to cope with testability like Azure Function triggers. However, this should only apply when the service locator is the only option. Luckily, Azure WebJobs provides an interface called
IJobActivator, which helps us easily integrate WebJob with an IoC container. WebJobActivator.Autofac is one of implementations of the
IJobActivator with Autofac. Let’s have a look how the NuGet package has implemented the interface.
DISCLAIMER: I am the author of the NuGet package, WebJobActivator.Autofac.
When we decompile the
IJobActivator interface, we see that it contains only one method
CreateInstance(), which is insufficient for any IoC container library because we need to register dependencies beforehand. Therefore, we need to extend the interface, called
IWebJobActivator. The new interface declares another method,
RegisterDependencies(THandler handler = default(THandler)).
RegistrationHandler class is optional, so we can omit it for actual implementation. But the handler is rather useful for unit testing. We’ll touch this later in this post. Here’s the abstract class that implements
As we can see, the implemented method barely does registration. We need an IoC container library here.
Integrating with Autofac
Now, let’s implement the extended interface with Autofac. Here’s the actual implementation:
With Autofac, the
AutofacJobActivator does actual dependencies registration process. One of the most powerful features that Autofac offers is
Module. We can register dependencies by grouping as a module. For our purpose, the
RegistrationHandler can be a perfect place to implement this module. Here’s the handler implementations:
As we can see,
AutofacRegistrationHandler implements a property of
Action to register a module. Here’s the sample module:
We’re all set. Let’s change the
Program.cs to apply
Main() method can be modified like this:
Inside the method, we instantiate
AutufacRegistrationHandler and register
AutofacJobActivator and register dependencies using the handler, and add the activator to
JobHostConfiguration. Now, we can finally remove all the
static modifier from the function class:
So far, we’ve extended
IWebJobActivator and implemented
AutofacJobActivator to configure
JobHost. However, I’m still not happy because there are two instances remain tightly coupled within the
Main() method –
JobHost. We also need to decouple those two instances.
JobHostConfigurationBuilder is basically a wrapper class of
JobHostconfiguration, with a fluent method,
AddConfiguration(Action). Let’s have a look.
This builder class gets the activator instance as a parameter and internally creates an instance of the
JobHostConfiguration. Now, we’ve got
JobHostConfiguration decoupled. Let’s move on.
This is the last step.
JobHostBuilder is another wrapper class of
JobHost and here’s the implementation.
Nothing special. It gets the
JobHostConfigurationBuilder, internally creates a
JobHostConfiguration instance, create a
JobHost instance, and run the host instance. This now needs to be integrated with Autofac like:
AutofacJobHostBuilder accepts Autofac’s module instance which help register dependencies. We’ve all set now. Let’s make another change on the
Putting Them Altogether
This is the final version of
Program.cs with full testability.
As a static property,
WebJobHost gets the
AutofacJobHostBuilder class with dependencies and additional configurations. After that, within the
Main() method, it builds JobHost and runs the instance. While performing unit tests, this
Program.cs can be also testable by mocking and injecting a dependency of
So far, we’ve walked through how an Azure WebJob application can be written by being decoupled and considering testability. With this approach, we don’t even need to run Storage Emulator in our local environment for testing. Happy coding!