简体   繁体   中英

How to set ASP.NET API with test in separate project to use one IoC/DI container

I'm quite new to unit testing and I struggle one thing. I want to create WebAPI in ASP.NET MVC with test project containing test methods for the controllers. I've read quite a lot about IoC/DI and I've already used it in other projects, but not with unit testing. As one of many advatages of IoC/DI is often mentioned mock classes injection for test methods, but I've never find a way how to do it using separate projects.

So how do I set the IoC/DI container so it contains both production and mock classes, but of course the mock classes are not interfearing with the production code and are separately located and only visible in the test project?

Short answer, you don't.

Each application should have its own composition root . Since unit tests are placed in a separate project and run under a separate process from your WebApi project, they are separate applications. Thus, they will have separate DI configurations. So in a nutshell 1 executable process == 1 composition root.

DI is a pattern. It does not require a DI container . Therefore, neither your WebApi project nor your unit test project require a DI container.

Although some people prefer to use a DI container during unit testing, to me it seems like overkill. Unit testing is about testing 1 class under test at a time. The rest of the classes in the test scenario should all be stubs or mocks . If following good design practices (not using constructor over-injection ), you will typically have no more than 4 instances in a scenario - the class under test and up to 3 fake classes. Using the new keyword to create these instances is not only simpler, it makes the unit tests easier to understand. And one important aspect of unit tests is to make them easy to understand so other people can easily see what is being tested and how so they can be used to understand the API when the documentation is not clear.

During integration testing or user acceptance testing , you may consider using DI more seriously to compose the components together because in those situations you typically have more than one class under test to compose together.

First I completely agree with @NightOwl888, you should not use IoC containers in UT , however I've seen some projects where the IoC is coupled with the system code, In those cases it is easy to inject the dependency using the IoC container.

In unit testing you first simulate the conditions for the behavior you want to verify, then execute the unit and then verify the behavior( AAA Pattern ). When you use IoC conteiners you usally do it with the RRR Pattern which fits together with the AAA pattern.

So how do I set the IoC/DI container so it contains both production and mock classes?

It's a little bit depends on the IoC container you use, but in the bottom line the concept is same:

In the Arrange section:

  1. You load your production registrations.
  2. You create the fakes objects and override the production registration with them.
  3. You resolve the class under test(now the CUT has your fakes as a dependencies...)

  4. Usually you should release objects in the TearDown ...

Each IoC container allows you to do it in a different way; Autofac use the last registration, Castle Windsor has IsDefualt method(there are more way to do it castle..) and so on...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM