How to use Unity for dependency injection (simple example) - c#

Consider this class with these two constructors:
public class DocumentService
{
private IDocumentDbService documentDbService;
private IDirectoryService directoryService;
private IFileService fileService;
// Constructor
public DocumentService()
{
this.documentDbService = new DocumentDbService();
this.directoryService = new DirectoryInfo();
this.filService = new FileInfo();
}
// Injection Constructor
public DocumentService(IDocumentDbService dbs, IDirectoryService ds, IFileService fs)
{
this.documentDService = dbs;
this.directoryService = ds;
this.fileService = fs;
}
}
I use the second constructor to mock the dependencies for unit testing.
Some times there are too many dependencies, so the injection constructor would have too many parameters.
So, I want to use Unity dependency injection.
Question
How can I refactor this code to use Unity instead?
(After reading Unity documents, still not sure how to use it correctly on my codes.)

Assuming you want to simplify unit test code to avoid manually setting up each dependency in every test:
You can setup container and add all necessary mocks there and than Resolve you class for the test like:
// that initialization can be shared
var container = new UnityContainer();
// register all mocks (i.e. created with Moq)
container.RegisterInstnce<IDocumentDbService>(Mock.Of<IDocumentDbService> ());
// resolve your class under test
var documentService = container.Resolve<DocumentService>();
Assert.AreEqual(42, documentService.GetSomething());

I quess you want to inject dependencies in both situations: in (unit)tests (e.g. using RhinoMocks) and real implementation (using Unity). The refactoring implies in that case that you should remove the the first constructor (of class DocumentService). Needed configuration in your dependencies should be loaded inside the dependency itself: DocumentDbService, DirectoryInfo, FileInfo. More information (like Dependency Injection Lifecycle) and some examples are available on MSDN, see https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx

Related

Simple Injector explicit attribute injection - property is null inside constructor

New to Simple Injector, trying to get some pieces working for a prototype. I am creating a WPF application that uses Simple Injector and ReactiveUI, but can't seem to get explicit property injection via attribute to trigger. The specific example I am working through is just testing injection of a logger. The plan is to roll this into a decorator, but I have run across the need for attribute injection with previous projects/DI libraries. Just want to verify I am able to use it.
Snippet of the bootstrapping:
private Container RegisterDependencies(Container container = null)
{
container ??= new Container();
// Container initialization that must precede dependency registration
// occurs here
// Enable property injection via the [Import] attribute
container.Options.PropertySelectionBehavior =
new ImportPropertySelectionBehavior();
SimpleInjectorInitializer initializer = new SimpleInjectorInitializer();
Locator.SetLocator(initializer);
Locator.CurrentMutable.InitializeSplat();
Locator.CurrentMutable.InitializeReactiveUI();
container.UseSimpleInjectorDependencyResolver(initializer);
container.RegisterConditional(
typeof(ILogger),
c => typeof(NLogLogger<>)
.MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
container.Register<MainWindow>();
container.Register<ISystem, System>(Lifestyle.Singleton);
container.Verify();
return container;
}
An instance of the System is requested from the DI container in the static RunApplication called from Main:
var system = container.GetInstance<ISystem>();
And here is the property injection in the system:
public class System : ISystem
{
[Import] public ILogger Logger { get; set; }
public System()
{
// Logger is null here. NullReferenceException is thrown
Logger.LogInfo("Creating System");
}
}
At this point in the constructor, the Logger property is null and attempt to log fails with exception. I should mention the ILogger is my own abstraction of NLog. If I instead perform constructor injection:
public System(ILogger logger)
Simple Injector picks up on this and resolves the dependency fine. I have tried changing the Import attribute to a different custom-defined Dependency attribute, no change. Have also tried just instantiating the logger as a singleton, same behavior.
Really appreciate any ideas, I'm running dry on searching forums, the SimpleInjector/ReactiveUI docs, and Steven's DI book.
Edit - here is the PropertySelectionBehavior code as well:
public class PropertySelectionBehavior<T> : IPropertySelectionBehavior
where T : Attribute
{
public bool SelectProperty(
Type implementationType, PropertyInfo propertyInfo) =>
propertyInfo.GetCustomAttributes(typeof(T)).Any();
}
public class ImportPropertySelectionBehavior :
PropertySelectionBehavior<ImportAttribute> { }
2nd Edit - I can take out all of the initialization related to ReactiveUI and still reproduce same behavior. New sample looks like:
private Container RegisterDependencies(Container container = null)
{
container ??= new Container();
container.Options.PropertySelectionBehavior =
new ImportPropertySelectionBehavior();
// Logger registration
container.RegisterConditional(
typeof(ILogger),
c => typeof(NLogLogger<>)
.MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
// UI registration
container.Register<MainWindow>();
//container.Register<MainWindowViewModel>();
container.Register<ISystem, System>(Lifestyle.Singleton);
container.Verify();
return container;
}
You are using the Logger property from inside System's constructor. Properties, however, are only initialized after the constructor finished. If you remove Simple Injector from the equation, and fallback to plain old C#, you would see the same. For instance:
var system = new System() // <-- constructor call
{
Logger = new NLogLogger<System>() // Logger_set is called after the ctor
};
If you run this code, you will see the same NullReferenceException thrown by the constructor of System.
What this means is that you shouldn't use any properties from inside your constructor. Even more broadly, from a DI perspective, you shouldn't use any service inside your constructor (or during construction for that matter) as is described by Mark Seemann here.
Update, the explicit property injection is working fine. It occurs after construction. I imagine there are design reasons for this, although somehow it was contrary to my mental model that the property injection would be performed on-demand/on first use.
Planning on experimenting a bit more to see what control is available over the timing to resolve property dependencies. If anyone who is more experienced has any advice on that or can point me to additional documentation I would welcome it. The decorator sounds like the more elegant way to make sure the logger is available as expected and allow independent lazy loading of decoratee concerns. Some discussion here:
SimpleInjector - "Lazy" Instantiate a singleton that has dependencies on first use

Dependency injection using options pattern

I am building an application which uses dependency injection following the options pattern design. I have a custom ORM class named DataManager. When I create an instance of DataManager I inject the connection string into the class as below.
public class DataManager : CommonDataManager {
private readonly ConnectionStrings _connectionStrings;
public DataManager(IOptions<ConnectionStrings> options) {
this._connectionStrings = options.Value;
}
When creating the DataManager object which parameter should I use? What should the initialisation code look like?
DataManager dm = new DataManager(?);
DI integration means that the DI engine is going to be responsible for object creation. So instead of directly initializing your class, you should rather do the following. Register also your DataManager with DI, so you can later instantiate it from serviceCollection:
In your ConfigureServices method add the following:
services.AddTransient<DataManager>();
Note, that you should decide the lifespan of your instance (I've chosen Transient here, but it's up to you - Singletone, Scoped, ...).
And then when you need to instantiate it, call as follows:
serviceProvider.GetRequiredService<DataManager>();
If, however, you want to go with your approach and want to instantiate the DataManager yourself, you should get the parameter from IoC container as follows:
DataManager dm = new DataManager(sp.GetRequiredService<IOptions<ConnectionStrings>>());
Note: that in both cases I assume that you've already registered the options with the DI in your Startup.ConfigureServices method.

Overriding StructureMap Registry from Another Project

I have a Unit Test project & want to shim-in Stub implementations for the repositories within a Unit of Work class. I would know how to do it using other IoC technologies, but am new to StructureMap.
How do I redefine & substitute a definition from inside my Unit Test project
What does that look like?
I'm having trouble finding good documentation on this.
DEFAULT CONTAINER:
Below is part of the business registry I hope to override.
public ContainerRegistry()
{
Scan(...);
// --------
// UNIT OF WORK
// This is the DEFAULT implementation
For(typeof(IRepository<>)).Use(typeof(GenericRepository<>));
For<IUnitOfWork>().Use<MeasurementContractsUnitOfWork>();
}
FOR UNIT TESTS:
In the unit test project I want IoC to use this instead:
// This is the STUB Implementation
For(typeof(IRepository<>)).Use(typeof(GenericRepositoryStub<>));
THE OBJECTIVE:
The objective is to simply use the container, as normal, but get the STUB shimmed-in AUTOMATICALLY.
var container = IoC.Initialize();
var uow = container.GetInstance<IUnitOfWork>()
I am unsure if this is the right way to do it, but this is how I accomplished my goal. If someone gives a better answer, I will mark theirs as correct:
I created separate IOC Initializer & ContainerRegistry classes within the Unit Test project, like so...
INITIALIZER CLASS:
public static class IoC
{
public static IContainer Initialize()
{
var container = new Container();
// NOTE: If you have many Registries to consider, you can add them (order matters)
// The Business Registry
container.Configure(x => x.AddRegistry<Business.DependencyResolution.ContainerRegistry>());
// The UnitTest Projects Registry (order matters)
container.Configure(x => x.AddRegistry<ContainerRegistry>());
return container;
}
}
REGISTRY CLASS:
public class ContainerRegistry : Registry
{
public ContainerRegistry()
{
// The Override
For(typeof(IRepository<>)).Use(typeof(GenericRepositoryIdentifiableStub<>));
}
}

Unit Test with Ninject Instantiate

I'm trying to test my service using ninject and an unit test project with visual studio 2012. My inject works ok on my controllers, but when I try to do the same in the unit test class I get an Exception.
System.NullReferenceException: Object reference not set to an instance of an object.
namespace Trex.UnitTests
{
[TestClass]
public class GiftServiceTests
{
private IGiftService _giftService;
public void GiftServiceTest(IGiftService giftService)
{
_giftService = giftService;
}
[TestMethod]
public void AddGift()
{
var list = _gift.FindAll(); <--- this line throw an exception
}
}
}
I think there is something wrong with the injection but I dont get it.
It looks to me like a typo of _giftService. In addition, attribute [TestInitialize] needs to be used in your constructor.
Try the following code by placing the correct service name _giftService - that your code is injecting instead:
var list = __giftService.FindAll();
Edit: Unit testing should be done without Ninject. Just create an instance of the object under test and inject a mock for every dependency manually.
Here is a sample with [TestInitialize]:
The unit test must have a default constructor:
[TestClass]
public class TestControllersHomeController
{
private HomeController _sut;
[TestInitialize]
public void MyTestInitialize()
{
var kernel = NinjectWebCommon.CreatePublicKernel();
_sut = kernel.Resolve<HomeController>();
}
[TestMethod]
public void TestIndex()
{
var result = _sut.Index();
Assert.IsNotNull(result);
}
}
The only way dependency injection is able to call your constructor and fill it with a parameter that has a value is if the dependency injection kernel is the one that instantiates your class.
In your case, MSTest is instantiating your test class, so Ninject does not have a chance to call your constructor.
To be honest, you are going about this the wrong way. You will battle MSTest if you pursue this further to try to get Ninject (or any other DI framework) to instantiate your test classes.
I would recommend you use 'new' to instantiate the class under test (_giftService = new GiftService();). If that class has dependencies in its constructor, use a mocking framework to pass in mocked version of those dependencies. This way you isolate your unit tests to only the functionality of the class under test.
_gift is null. Your variable is _giftService. You also should use the [TestInitialize] attribute for your constructor.
Extra tip:
You shouldn't create any dependencies in your unit test. So the giftService which you want to use should be a mock or a stub.

Best approach for breaking dependencies in C#?

We are looking at adding unit tests to our C# code base. I am finding it easy to add unit tests to simple classes, but classes that interact with other dependencies are more difficult. I have been looking at mocking frameworks, but was wondering about the best approach to write classes in the first place to break external dependencies, like file system, database and messaging system dependencies.
To give an example, a routine listens on a socket for a message in a certain format - say MessageA. This is decoded, some calculations are done, this is re-encoded into a different binary format and the resulting message then sent, MessageB.
My current testing approach is as follows. I extract an interface for all socket interactions, and create a mock interface. I set the interface in a singleton. Then run the class against hard coded inputs. The class under test will use the interface in the singleton to send/receive.
I do a similar thing to test database interactions.
This does not seem like the most flexible approach, how would you go about improving this to make it easier to test? If a mocking framework is the answer, how would I design the classes?
Example code :
[SetUp]
public void init()
{
// set message interface in singleton as mock interface
CommAdapter.Instance.MessageAdapter = new MockMessage();
// build reference message from hard coded test variables
initialiseMessageA();
// set input from mock message socket
((MockMessage) CommAdapter.Instance.MessageAdapter).MessageIn = m_messageA;
}
[Test]
public void test_listenMessage_validOutput()
{
// initialise test class
MessageSocket tS = new MessageSocket();
// read from socket
tS.listenMessage();
// extract mock interface from singleton
MockMessage mm = ((MockMessage) CommAdapter.Instance.MessageAdapter);
// assert sent message is in correct / correstpoinding format
Assert.AreEqual(1000001, mm.SentMessageB.TestField);
}
Instead of using Singletons to set your component implementations, use a Dependency Injection, and a DI library like Ninject. This is exactly the type of scenario they were designed for.
Not pushing you to Ninject specifically, but they have a good tutorial :) The concepts will transfer to other frameworks (like Unity).
https://github.com/ninject/ninject/wiki
With DI alone, the code will look something like this:
class Samurai {
private IWeapon _weapon;
public Samurai(IWeapon weapon) {
_weapon = weapon;
}
public void Attack(string target) {
_weapon.Hit(target);
}
}
class Shuriken : IWeapon {
public void Hit(string target) {
Console.WriteLine("Pierced {0}'s armor", target);
}
}
class Program {
public static void Main() {
Samurai warrior1 = new Samurai(new Shuriken());
Samurai warrior2 = new Samurai(new Sword());
warrior1.Attack("the evildoers");
warrior2.Attack("the evildoers");
}
}
This looks clean now, but wait until your dependencies have dependencies, or further :) You can use a DI library to solve that, though.
With a library to handle the wiring up for you, it will look something like:
class Program {
public static void Main() {
using(IKernel kernel = new StandardKernel(new WeaponsModule()))
{
var samurai = kernel.Get<Samurai>();
warrior1.Attack("the evildoers");
}
}
}
// Todo: Duplicate class definitions from above...
public class WarriorModule : NinjectModule {
public override void Load() {
Bind<IWeapon>().To<Sword>();
Bind<Samurai>().ToSelf().InSingletonScope();
}
}
With either of these approaches, plus a mock object framework like Moq, your unit tests look something like this:
[Test]
public void HitShouldBeCalledByAttack()
{
// Arrange all our data for testing
const string target = "the evildoers";
var mock = new Mock<IWeapon>();
mock.Setup(w => w.Hit(target))
.AtMostOnce();
IWeapon mockWeapon = mock.Object;
var warrior1 = new Samurai(mockWeapon);
// Act on our code under test
warrior1.Attack(target);
// Assert Hit was called
mock.Verify(w => w.Hit(target));
}
You'll notice you can just pass mock instances straight into the code under test, and you don't have to mess around with setting singletons. This will help you avoid problems like needing to set up the state multiple times, or in between calls. It means no hidden dependencies.
You'll also notice I didn't use the DI container in the tests. If your code is well factored, it will only be testing a single class (and as often as possible, only a single method), and you will only need to mock out the direct dependencies of that class.
In addition to a DI container (I'm using MS Unity 2.0 currently but there are many to choose from) you will need a good mocking framework, my preference is MOQ. A common pattern/process for breaking concrete dependencies is:
define the dependency via an interface; you may luck out and already have an interface, like IDbConnection or you may need to use Proxy to wrap a concrete type and define your own interface.
resolve the concrete implementation via your DI container
inject your mock implementations into your DI container at test setup time (inject real impls. at system startup)

Categories