MVC Integration tests with Unity IoC - c#

Am trying Unity IoC, after using constructor based DI.
Problem is trying to get integration tests working.
http://patrick.lioi.net/2013/06/20/streamlined-integration-tests/
"Running your integration tests should exercise as much of the real system as is reasonably possible"
Patrick above describes setting up an IoC inside the MVC Unit test project.. but I'm stuck as to how to implement
public class HomeController : Controller
{
readonly IWinterDb db;
// Unity knows that if IWinterDb interface is asked for, it will inject in a new WinterDb()
public HomeController(IWinterDb db)
{
this.db = db;
}
public ActionResult Index()
{
var stories = db.Query<Story>()
.OrderByDescending(s => s.Rating)
.Include(s => s.StoryType);
return View(stories);
}
Unit tests are fine, passing in a fake:
[TestMethod]
public void Index_GivenFake_ShouldReturn100Stories()
{
var db = new FakeWinterDb();
db.AddSet(TestData.Stories);
var controller = new HomeController(db);
var result = controller.Index() as ViewResult;
var model = result.Model as IEnumerable<Story>;
Assert.AreEqual(100, model.Count());
}
However I like integration tests which test the whole stack:
//Integration tests depend on the test data inserted in migrations
[TestClass]
public class HomeControllerTestsIntegration
{
[TestMethod]
public void Index_GivenNothing_ResultShouldNotBeNull()
{
var controller = new HomeController();
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result);
}
Problem: This will not compile (as no parameterless constructor). And Unity is not being called to inject in the correct dependency for HomeController.
Unity wire up:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
container.RegisterType<IWinterDb, WinterDb>();
// for authentication
container.RegisterType<AccountController>(new InjectionConstructor());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
Edit1:
[TestMethod]
public void Index_GivenNothing_ResultShouldNotBeNull()
{
UnityConfig.RegisterComponents();
var controller = UnityConfig.container.Resolve<HomeController>();
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result);
}
Making sure the singleton is there.
public static class UnityConfig
{
public static UnityContainer container;
public static void RegisterComponents()
{
container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
//container.RegisterType<IWinterDb, WinterDb>();
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface, // Convention of an I in front of interface name
WithName.Default
); // Default not a singleton in Unity
// for authentication
container.RegisterType<AccountController>(new InjectionConstructor());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
Exposing Unity to the test project

You need to resolve your controller via the container for Unity to resolve dependencies for you.
It may be as simple as replacing this:
var controller = new HomeController();
with this:
var controller = container.Resolve<HomeController>();
You will obviously need to expose your container to your test class. This is something you would not normally do when wiring up your production code.

Related

Structure Map - Replace Interface with mock object at runtime

I am doing some integration tests for my OWIN based Web API. I am using structure map as DI container. In one of the cases, I need to mock out an API call ( can't include it as part of the test).
How would I go about doing this using Structure Map? I have done it using SimpleInjector but the code base I am working on is using Structure Map and I can't figure out how I would do this.
Solution with SimpleInjector:
Startup.cs
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
app.UseWebApi(WebApiConfig.Register(config));
// Register IOC containers
IOCConfig.RegisterServices(config);
}
ICOCConfig:
public static Container Container { get; set; }
public static void RegisterServices(HttpConfiguration config)
{
Container = new Container();
// Register
config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(Container);
}
And in my Integration test, I mock out the interface that calls the other API.
private TestServer testServer;
private Mock<IShopApiHelper> apiHelper;
[TestInitialize]
public void Intitialize()
{
testServer= TestServer.Create<Startup>();
apiHelper= new Mock<IShopApiHelper>();
}
[TestMethod]
public async Task Create_Test()
{
//Arrange
apiHelper.Setup(x => x.CreateClientAsync())
.Returns(Task.FromResult(true);
IOCConfig.Container.Options.AllowOverridingRegistrations = true;
IOCConfig.Container.Register<IShopApiHelper>(() => apiHelper.Object, Lifestyle.Transient);
//Act
var response = await testServer.HttpClient.PostAsJsonAsync("/api/clients", CreateObject());
//Assert
Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);
}
I found this in the structure-map documentation but it doesn't allow me to inject a mock object in there (only types).
How I can inject a mock version of IShopApiHelper (Mock) when running my integration tests? (I am using the Moq library for mocking)
Assuming the same API structure as in the original example you can do basically the same thing as demonstrated in the linked documentation.
[TestMethod]
public async Task Create_Test() {
//Arrange
apiHelper.Setup(x => x.CreateClientAsync())
.Returns(Task.FromResult(true);
// Use the Inject method that's just syntactical
// sugar for replacing the default of one type at a time
IOCConfig.Container.Inject<IShopApiHelper>(() => apiHelper.Object);
//Act
var response = await testServer.HttpClient.PostAsJsonAsync("/api/clients", CreateObject());
//Assert
Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);
}

Log4Net on a MVC web solution

I'm creating a solution that contains two projects: the web project ant it's test project. I'm using Log4net for logging purposes, CastleWindsor for dependency injection and moq for the tests.
The problem I have is the configuration of the test. I want to test the HomeController that is Logging to a file, but when I run the test I don't want to Log, I think is absurd.
Is there a way to skip Logging in the test project?
The HomeController class:
public class HomeController : Controller
{
// this is Castle.Core.Logging.ILogger, not log4net.Core.ILogger
public ILogger Logger { get; set; }
private IRowan _rowan;
public HomeController(IRowan rowan)
{
_rowan = rowan;
}
public ActionResult Index()
{
//In the [tests] Logger fails
Logger.Debug("GET Request traced");
Logger.Error("Example of Error");
String test = _rowan.DoSomething();
ViewBag.Title = test;
return View();
}
}
}
It's test:
[TestClass]
public class HomeControllerTest
{
private static WindsorContainer _container;
[ClassInitialize()]
public static void InstallWindsor()
{
_container = new WindsorContainer();
// configure other classes
}
[ClassCleanup()]
public static void DisposeContainer()
{
_container.Dispose();
}
[TestMethod]
public void Index()
{
// Disponer
var mock = new Mock<IRowan>();
mock.Setup(m => m.DoSomething()).Returns("Home Page");
HomeController controller = new HomeController(mock.Object);
// Actuar
ViewResult result = controller.Index() as ViewResult;
// Declarar
Assert.IsNotNull(result);
Assert.AreEqual("Home Page", result.ViewBag.Title);
}
}
If the answer is no, which is the best way to implement log4net for testing?
PD: When I run the code, It works fine. When I run the test, Logger throws an exception because is null.
PD: I'm starting using the Microsoft Technology.
You could mock your Logger and set it on your controller like so:
Mock<ILogger> mockLogger = new Mock<ILogger>();
controller.Logger = mockLogger.Object;
Note that you shouldn't really need to use CastleWindsor in your tests. That's useful for controlling the lifecycle of objects in your application but in your tests you should be injecting things by hand. You are actually doing this in the example above. From the code you've posted you can remove the ClassInitialize and ClassCleanup functions and it will run the same.
You can use an other config for your test project.
Read more: https://logging.apache.org/log4net/release/manual/configuration.html

Unity Config error in console application

Hi am working on console application which uses Dependency Injection pattern, i have created the interface like
public interface IRecurringTransactionPlanDataService : IService<RecurringTransactionPlan>
{
IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData();
}
and the class implements as
public class RecurringTransactionPlanDataService : Service<RecurringTransactionPlan>, IRecurringTransactionPlanDataService
{
private readonly IRepositoryAsync<RecurringTransactionPlan> _repository;
public RecurringTransactionPlanDataService(IRepositoryAsync<RecurringTransactionPlan> repository)
: base(repository)
{
_repository = repository;
}
public IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData()
{
return _repository.RecurringTransactionPlanData();
}
}
The repository:
public static class RecurringTransactionPlanRepository
{
public static IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData(this IRepository<RecurringTransactionPlan> repository)
{
return repository.Queryable();
}
}
the above code all in separate projects, i am using this in MVC and also in console application, while using in MVC there is no error fetching data from db by UnityConfig.cs, but in console application we need to manually register and resolve the interfaces, i have tried this,
My Console Application:
public class RecurringTransaction
{
public readonly IRecurringTransactionPlanDataService _recurringTransactionPlanDataService;
public RecurringTransaction()
{
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
}
}
public class Program
{
public static void Main(string[] args)
{
FeePaymentTracker.UnityConfig.RegisterComponents();
RecurringTransaction rt = new RecurringTransaction();
var restult = rt.GetRecurringTransactionRecords();
}
}
am getting the above error. expecting your ideas to resolve the error.
In your RecurringTransaction-method you create a new container and then you register RecurringTransactionPlanDataService in that new container. But you do not register the dependencies that the implementation RecurringTransactionPlanDataService has. That container will only have one registration.
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
Since RecurringTransactionPlanDataService has a dependency to IRepositoryAsync<RecurringTransactionPlan> you need to register that as well.
Change your code to:
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
container.RegisterType<IRepositoryAsync<RecurringTransactionPlan>, YourRepositoryImplementation>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
As a sidenote you may want to re-use the same container. In console-applications I usually resolve a "ProgramStarter", which then gets the correct injections. This way you only need to use the service locator anti-pattern in the root. But can use proper DI in the rest of the application.
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ProgramStarter, ProgramStarter>();
// Pass the same container to the config.
FeePaymentTracker.UnityConfig.RegisterComponents(container);
var program = container.Resolve<ProgramStarter>();
program.Run();
}
}
public class ProgramStarter
{
IRecurringTransactionPlanDataService _dataService;
public ProgramStarter(IRecurringTransactionPlanDataService dataService)
{
_dataService = dataService;
}
public void Run()
{
// Do stuff.
}
}
in the code that you have posted you have an interface called IPaymentService and its implementation. It seems ok. But then in the screenshot you are trying to resolve a dependency called RecurringTransactionPlanDataService. Make your that you have registered this dependency. Could you add information about how you are registering the dependencies in the container?
The problem in your code is that you are trying to resolve the implementation instead of the interface. You should change the following line:
_recurringTransactionPlanDataService = container.Resolve<RecurringTransactionPlanDataService>();
with that:
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
Cheers,

Unity - How to avoid circular reference?

I'm trying to implement dependency injection in my ASP.NET MVC Project using Unity and would like some advice on how to avoid circular references.
At my work we used to implement the service locator pattern, which returned a singleton for each individual service of the application.
public class ServiceWrapper
{
private UserService _userService;
private ProductService _productService;
public UserService User
{
if(_userService == null)
{
_userService = new UserService();
}
return _userService;
}
public ProductService Product
{
if(_productService == null)
{
_productService = new ProductService();
}
return _productService;
}
}
Then in the controller, you could easily access all the services by instantiating the ServiceWrapper and calling methods, like:
private ServiceWrapper _services = new ServiceWrapper();
public ActionResult Index()
{
List<Product> products = _services.Product.GetProducts();
return View(products);
}
Setting up DI using Unity was a breeze. I created a container in Application_Start() (global.asax), like so:
var container = new UnityContainer();
container.RegisterType<IUserService, UserService>(new ContainerControlledLifetimeManager());
container.RegisterType<IProductService, ProductService>(new ContainerControlledLifetimeManager());
container.RegisterType<IServiceWrapper, ServiceWrapper>(new ContainerControlledLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
The ServiceWrapper is registered as a Singleton. And implemented constructor injection as follows:
public class ProductController: Controller
{
private IServiceWrapper _services;
public ProductController(IServiceWrapper services)
{
_services = services;
}
public ActionResult Index()
{
List<Product> products = _services.Products.GetProducts();
return View(products);
}
That worked beautifully. But then I came accross the problem.
We like every service to also have a property containing the ServiceWrapper, so that you can easily access the other services from within another, like so:
public class ProductService
{
private IServiceWrapper _services;
public ProductService(IServiceWrapper services)
{
_services = services;
}
public IServiceWrapper Services { get { return _services; } }
}
But when I implemented constructor injection of the ServiceWrapper in the individual services, it resulted in a stackoverflow exception due to circular referencing.
I read that Unity does not support circular referencing. Is there a (solid) way around this. Or should I implement a different architecture? If so, could you recommend a solution?
The way this is typically done is to declare just the services you need and have them ctor-injected. Don't inject a "ServiceWrapper" which just contains everything. Inject what you need. As the container builds up your type you don't have to worry about providing the services. They will be just there.
The development workflow often goes like this:
Add a new dependency injected field
Delete the existing ctor
Regenerate the ctor using Resharper: alt+ins, generate ctor.

Unit test unityContainer.Resolve

In a class I am using this code:
public User CurrentUser
{
get
{
var unityContainer = new UnityContainer();
var httpContextHelper = unityContainer.Resolve<HttpContextHelper>();
return httpContextHelper.GetUser();
}
}
This is in the Bootstrapper.cs file:
public static class Bootstrapper
{
public static void Initialise()
{
IUnityContainer unityContainer = new UnityContainer();
unityContainer.RegisterType<IHttpContextHelper, HttpContextHelper>();
DependencyResolver.SetResolver(new UnityDependencyResolver(unityContainer));
}
}
I cannot use constructor injection here because it is a base class and it would take quite some work to refactor.
But how would I unit test this? I cannot find a suitable method to mock unityContainer.Resolve.
First things first the following code is wrong:
get
{
var unityContainer = new UnityContainer();
var httpContextHelper = unityContainer.Resolve<HttpContextHelper>();
return httpContextHelper.GetUser();
}
You are creating a new Unity container which of course is empty and then you are attempting to resolve some instances from this container which would simply call the default constructor of the HttpContextHelper class. Gosh I hate Unity for not throwing an exception when you attempt to resolve an instance of something that has never been registered into the container (which is what you are doing here). Instead it is silently calling its constructor with most known (registered) dependencies.
So this will not return the instance you have registered in your Bootstrapper because there you have a different instance of the UnityContainer in which you have registered the IHttpContextHelper instance.
So the first step towards refactoring this is to use the DependencyResolver:
public User CurrentUser
{
get
{
var httpContextHelper = DependencyResolver
.Current
.GetService<IHttpContextHelper>();
return httpContextHelper.GetUser();
}
}
Now in your unit test you could write a custom dependency resolver:
public class DepepndecyResolverMock : IDependencyResolver
{
private readonly IDictionary<Type, object> kernel;
public DepepndecyResolverMock(IDictionary<Type, object> kernel)
{
this.kernel = kernel;
}
public object GetService(Type serviceType)
{
return this.kernel[serviceType];
}
public IEnumerable<object> GetServices(Type serviceType)
{
throw new NotImplementedException();
}
}
which you could configure for your tests:
var kernel = new Dictionary<Type, object>
{
{ typeof(IHttpContextHelper), new HttpContextHelperMock() }
};
DependencyResolver.SetResolver(new DepepndecyResolverMock(kernel));
This being said, this code is still horribly wrong. It might allow you to unit test it but please I insist, this is wrong design. Do not use it. This uses the service locator pattern which is an anti-pattern.
The proper way to do this is to invert the control of this class so that it doesn't need to fetch its dependencies, but its dependencies need to be injected into it. So instead of wasting your time in useless patterns, refactor your code so that it uses real dependency injection.

Categories