Category Archives: .NET Framework

Quartz.NET, Castle Windsor – LifeStyle Per Job (Scoped)

If you have ever tried to use Quartz.NET (a famous job-scheduling library) with Castle Windsor (IoC/DI container) you might need to register a component whose life-style should be bound to the job itself (LifestylePerJob). There are plenty of alternatives available which all have the same characteristics – they do not work:

  • LifestylePerThread – does not reset the thread when running a new job
  • BoundTo<Job>() – does not support typed factories when resolved inside the job
  • BoundTo<object>() – does not support typed factories when resolved inside the job
  • Quartz.IJobFactory + LifestyleScoped – does not support typed factories when resolved into the job (the scope from JobFactory is not propagated inside the job!)

There is a “simple” workaround for such scenarios. You can use LifestyleScoped but you have to begin/end the scope in the job.

If you use the job itself just as a plumbing class where the work itself is encapsulated in a separate service (and you should do this) then you can simply inject both a service-factory and the kernel and then do the scope-work in the job itself:

public class MyJob : IJob
{
    private readonly IServiceFactory<MyService> myServiceFactory;
    private readonly IKernel kernel;

    public MyJob(IServiceFactory<MyService> myServiceFactory, IKernel kernel)
    {
        this.myServiceFactory = myServiceFactory;
        this.kernel = kernel;
    }

    public void Execute()
    {
        using (var scope = kernel.BeginScope())
        {
            // use your way to work with factories ;-)
            using (var myService = myServiceFactory.Create())
            {
                myService.DoWork();
            }
            // BTW: we have an extension method
            myServiceFactory.ExecuteAction(service => service.DoWork());
        }
    }
}

…the MyService class has all the dependencies you need and as you use it using the factory it behaves as the pseudo-resolution-root for this scenario. You might use the kernel.Resolve+Release in the job but I always prefer not to… ;-)

References

Mocking a ConfigurationSection (or full configuration file)

In unit-tests you sometimes find yourself in a situation that you need to mock a configuration section. The ConfigurationSection class (or your inherited class) encapsulates nicely and there is no easy way how to break it’s read-only public interface.

You might consider abstracting the whole section and/or exposing it via some kind of adapter, but sometimes you don’t need to be 100% pure and still want get some basic test coverage.

There is an obscure but functional way how to mock the ConfigurationSection (or a whole configuration file if needed):

1. Create a fake configuration file in your test project

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<configSections>
<section name="mySection" type="MyConfigurationSection, MyAssembly" />
	</configSections>
	<mySection>
		<identities>
			<identity clientId="fake_id" name="FAKE_NAME" partitionName="FAKE_PARTITION" permissions="Full" />
		</identities>
	</mySection>
</configuration>

The file can be placed in any directory in test project. Right beside your test-class might be the right place.

2. Set the configuration file to be copied to build output

In Properties of the configuration file, set:

  • Build Action = Content
  • Copy to Output Directory = Copy always

3. Create a unit-test which uses the file to build a fake configuration

[TestClass]
public class MyServiceTests
{
	public TestContext TestContext { get; set; }

	[TestMethod]
	[DeploymentItem("PathInTestProject\\MyServiceTests_ScenarioName.config")]
	public void MyService_DoSomething_ScenarioName_ExpectedBehavior()
	{
		// arrange
		ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap()
		{
			ExeConfigFilename = Path.Combine(TestContext.DeploymentDirectory, "MyServiceTests_ScenarioName.config")
		};
		Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
		MyConfiguarionSection mySection = config.GetSection("mySection") as MyConfiguarionSection ;

		var sut = new MyService(mySection);

		// act
		...
	}
}

The basics:

  • The ConfigurationManager.OpenMappedExeConfiguration() method allows you to use any configuration file you want.
  • The [DeploymentItem(...)] attribute copies the config file from build output to the “test deployment directory” (e.g. $(SolutionDir)\TestResults\Deploy_username 2017-09-29 22_02_39\Out\)
  • The TestContext.DeploymentDirectory contains the path whereas the TestContext property is automatically injected with appropriate instance of the test context.