There are several problems with how you developed the application. First of all, you call the Ninject kernel directly from your code. This is called a service locator pattern and is considered an antivirus pattern . This greatly simplifies testing your application, and you are already experiencing it. You are trying to mock the Ninject container in the unit test, which complicates the situation.
Then you enter the primitive types ( string , bool ) in the constructor of your DirEnum type. I like how MNrydengren states this in the comments:
accept compile-time dependencies through constructor parameters and run-time dependencies using the Parameters method
It's hard for me to guess what this class should do, but since you insert these variables that change at run time into the DirEnum constructor, you get a complex test application.
There are several ways to fix this. Two that come to mind are using the injection method and using the factory. Which one is possible is up to you.
Using the injection method, your Configurator class will look like this:
class Configurator { private readonly IDirEnum dirEnum;
Using factory, you will need to define a factory that knows how to create new types of IDirEnum :
interface IDirEnumFactory { IDirEnum CreateDirEnum(string filePath, string fileFilter, bool includeSubDirs); }
Now your Configuration class may depend on the IDirEnumFactory interface:
class Configurator { private readonly IDirEnumFactory dirFactory;
See how in both examples dependencies are inserted into the Configurator class. This is called the dependency nesting pattern , the opposite of the Locator service pattern, where Configurator queries its dependencies by calling Ninject in the kernel.
Now, since your Configurator completely free of any IoC container, which is always the case, you can now easily test this class by introducing the mock version of the dependency that it expects.
It remains to configure the Ninject container at the top of the application (in DI terminology: root directory ). In the example of the method implementation, the configuration of your container will remain the same, with the factory example, you will need to replace the line Bind<IDirEnum>().To<DirEnum>() as follows:
public static void Bootstrap() { kernel.Bind<IDirEnumFactory>().To<DirEnumFactory>(); }
Of course, you will need to create a DirEnumFactory :
class DirEnumFactory : IDirEnumFactory { IDirEnum CreateDirEnum(string filePath, string fileFilter, bool includeSubDirs) { return new DirEnum(filePath, fileFilter, includeSubDirs); } }
WARNING : note that factory abstractions are in most cases not the best, as described here .
The last thing you need to do is create a new instance of Configurator . You can simply do it like this:
public static Configurator CreateConfigurator() { return kernel.Get<Configurator>(); } public static void Main(string[] args) { Bootstrap(): var configurator = CreateConfigurator(); configurator.ConfigureServices(args); }
Here we call the core. Although calling a container directly should be prevented, your application will always have at least one place where you call the container, simply because it needs to connect everything. However, we try to minimize the number of container calls directly, as it improves - among other things - the verifiability of our code.
See how I really did not answer your question, but showed a way to effectively solve the problem.
You might want to check the DI configuration. This is a very relevant IMO. I do this in my applications. But for this, you often do not need a DI container, or even if you do this, this does not mean that all your tests should have a dependency on the container. This ratio should exist only for tests that themselves test the DI configuration. Here is the test:
[TestMethod] public void DependencyConfiguration_IsConfiguredCorrectly() {
This test is indirectly dependent on Ninject, and it will not work when Ninject cannot create a new instance of Configurator . When you keep your constructors clean of any logic and use it only to store accepted dependencies in private fields, you can run this without risking accessing a database, web service or something.
Hope this helps.