How to resolve dependency in integration test Asp.Net MVC - c#

I don't have much experience with integration tests but I will try to explain what I am trying to do.
I have created an endpoint which reads data from database.
public class ProductController : Controller
{
private IProductService _productService;
public ProductController (IProductService productService)
{
_productService = productService;
}
[HttpGet]
public IEnumerable<Product> GetProducts()
{
return _productService.GetAllProducts();
}
}
public class ProductService: IProductService
{
private IProductRepository _productRepository;
public ProductService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
public List<Product> GetAllProducts()
{
return _productRepository.GetProducts();
}
}
public class ProductRepository: IProductRepository
{
public List<Product> GetProducts()
{
//database call to get products;
}
}
I have resolved dependencies for repository and other services using SimpleInjectorDependencyResolver.
Now I have created an unit test project where I have mocked the response from service.
[TestFixture]
public class ProductControllerTests
{
private Mock<IProductService> _productService;
private ProductController _productController;
[SetUp]
public void Setup()
{
_productService = new Mock<IProductService>();
_productController= new ProductController(_productService.Object);
}
}
this works fine. I can return the Mock data.
for integration tests I created a separate project in which I want to hit the repository and get the real data back, but how can I resolve the dependencies for IProductService in integration test so that I will hit the repository and I can get the real data from database back. How can use dependency injection in the integration test to resolve dependencies.
public class ProductControllerIntegrationTests
{
private ProductService _productService;
private ProductController _productController;
[SetUp]
public void Setup()
{
// how to resolve the dependency for _productService
_productController= new ProductController(_productService);
}
}

Related

ASP.NET Core dependency injection - How to create instances?

In Startup:
services.AddTransient<IMyService, MyService>()
Controller method:
[HttpGet]
public JsonResult GetSomething()
{
Helper helper = new Helper(new MyService()); // works but looking better solution
return Ok("");
}
Helper class:
public class Helper
{
private readonly IMyService myService;
public Helper(IMyService myService)
{
this.myService = myService;
}
public Helper()
{
this.myService = ?;
}
}
I want to instantiate Helper class without inject the dependency manually with new MyService().
The MyService() class should be the class in startup.
I also want to place the the Helper class in another assembly.
I see some code with
var service = (IFooService)serviceProvider.GetService(typeof(IMyService));
but i don't know how to get a serviceProvider instance without injecting it to the helper.
Add the helper to the container
services.AddTransient<IMyService, MyService>()
services.AddScoped<Helper>(sp => new Helper(sp.GetRequiredService<IMyService>()));
And explicitly inject it into the controller
public class MyController: Controller {
private readonly Helper helper;
public MyController(Helper helper) {
this.helper = helper;
}
[HttpGet]
public JsonResult GetSomething() {
//...use helper
return Ok("");
}
//...
}
Ideally the helper should be derived from an abstraction as well
public class Helper : IHelper {
private readonly IMyService myService;
public Helper(IMyService myService) {
this.myService = myService;
}
//...
}
And added accordingly to the container
services.AddTransient<IMyService, MyService>()
services.AddScoped<IHelper, Helper>();
to avoid the controller having tight coupling to concretions (implementation concerns).
public class MyController: Controller {
private readonly IHelper helper;
public MyController(IHelper helper) {
this.helper = helper;
}
[HttpGet]
public JsonResult GetSomething() {
//...use helper
return Ok("");
}
//...
}
A way to properly resolve the service via DI:
[HttpGet]
public JsonResult GetSomething([FromServices] IMyService myService)
{
Helper helper = new Helper(myService);
return Ok("");
}
Or you inject it via ctor and use it in the method.

Using inheritance and dependency injection at the same time

Here is how my application makes a call to the database:
Web App -> Business Layer -> Data Layer
Everything is using dependency injection.
For example:
In the controller in my Web app I make a call like this:
await _manager.GetCustomers();
Which goes into my Business Layer:
public class CustomerManager : ICustomerManager
{
private ICustomerRepo _repository;
public CustomerManager(ICustomerRepo repository)
{
_repository = repository;
}
public Task<IList<Customer>> GetCustomers(string name = null)
{
return _repository.GetCustomers(name);
}
}
Which goes into my Data Layer:
public class CustomerRepo : BaseRepo, ICustomerRepo
{
public CustomerRepo(IConfigurationRoot configRoot)
: base(configRoot)
{
}
public Customer Find(int id)
{
using (var connection = GetOpenConnection())
{
...
}
}
}
The trick here is that CustomerRepo inherits from BaseRepo to be able to use the GetOpenConnection() function. But at the same time BaseRepo needs an IConfigurationRoot injected into it from the web application. How can I do both?
public class BaseRepo
{
private readonly IConfigurationRoot config;
public BaseRepo(IConfigurationRoot config)
{
this.config = config;
}
public SqlConnection GetOpenConnection(bool mars = false)
{
string cs = config.GetSection("Data:DefaultConnection:ConnectionString").ToString();
...
}
}
How would you instantiate (or even compile) a CustomerRepo at all, regardless of dependency injection? You need an IConfigurationRoot parameter to pass through to the base constructor. Like:
public CustomerRepo(IConfigurationRoot configRoot)
: base(configRoot)
{
}
See https://msdn.microsoft.com/en-us/library/hfw7t1ce.aspx for info on the base keyword.

instantiates class using ninject ioc in .net

I am using Ninject to do some IoC in my ASP.NET MVC application.
I have an interface "IService.cs" :
public interface IService
{
string method();
}
I have the corresponding implementation "Service.cs" :
public class Service
{
string method()
{
return "result";
}
}
I have done the binding in another class heriting from NinjectModule :
public class MyNinjectModule : NinjectModule
{
public override void Load()
{
RegisterServices();
}
private void RegisterServices()
{
Kernel.Bind<IService>().To<Service>();
}
}
I have my class A which use this service :
public class A
{
private readonly IService _service;
private int i;
public A(IService service, int i)
{
this._service=service;
this.i=i;
}
}
The problem is that now, I don't know how to instantiate my class A in my application. This is where am I stuck, how can I call Ninject
to tell my app to go get the implementation of my interface:
var myClass=new A(????)
The main problem is that your Service class does not implement IService.
public class Service
{
string method()
{
return "result";
}
}
It should be
public class Service : IService
{
public string method()
{
return "result";
}
}
But as for instantiating a class, the best approach is to use a composition root to build an object graph. In MVC, that is best handled by implementing IControllerFactory.
public class NinjectControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public NinjectControllerFactory(IKernel kernel)
{
this.kernel = kernel;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController)this.kernel.Get(controllerType);
}
}
Usage
using System;
using Ninject;
using DI;
using DI.Ninject;
using DI.Ninject.Modules;
internal class CompositionRoot
{
public static void Compose()
{
// Create the DI container
var container = new StandardKernel();
// Setup configuration of DI
container.Load(new MyNinjectModule());
// Register our ControllerFactory with MVC
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(container));
}
}
In Application_Start, add:
CompositionRoot.Compose();
You will also need to create an interface for your class A and register it. An integer cannot be resolved automatically, you have to do that explicitly.
Kernel.Bind<IClassA>().To<A>()
.WithConstructorArgument("i", 12345);
And then you would add your dependency to a controller. Dependencies of dependencies are resolved automatically.
public class HomeController : Controller
{
private readonly IClassA classA;
public HomeController(IClassA classA)
{
if (classA == null)
throw new ArgumentNullException("classA");
this.classA = classA;
}
public ActionResult Index()
{
// Use this.classA here...
// IService will be automatically injected to it.
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
}

Unity, injecting instances to controller gives seemingly unrelated exception

This is what i want to be able to do (passing interface(s) to Controllers):
public class TestController : Controller
{
// GET: Test
[HttpGet]
public ActionResult Index(ITestService service)
{
var test = new TestModel();
test.Greeting = "yo" + service.GetString();
test.Name = "nils";
return View(test);
}
}
This is what i have put in Global.asax.cs in the Application_Start() to try to make that work:
// Create a new Unity dependency injection container
var unity = new UnityContainer();
unity.RegisterType<ITestService,TestService>();
// Finally, override the default dependency resolver with Unity
DependencyResolver.SetResolver(new IoCContainer(unity));
I have also, as you can see, created an IoCContainer class which looks as follows:
public class IoCContainer : IDependencyResolver
{
private readonly IUnityContainer _container;
public IoCContainer(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
if (_container.IsRegistered(serviceType))
return _container.Resolve(serviceType);
return null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (_container.IsRegistered(serviceType))
return _container.ResolveAll(serviceType);
return new List<object>();
}
public void Dispose()
{
_container.Dispose();
}
}
When i try to access the "http://humptidumptiurl/Test" it tells me:
A public action method 'Login' was not found on controller 'Companyname.Product.Web.Controllers.TestController'.
Now... i thought it should resolve the ITestService.. not bother about a completely different Controller? other controllers that does not use Unity yet, work as they have always done....
Inputs on how i could achieve my desired solution would be greatly appriciated
EDIT:
Thank you! Of course it injects through the constructor... I should have thought of that... but now it gives me this error message:
{"An error occurred when trying to create a controller of type 'Stimline.Xplorer.Web.Controllers.TestController'. Make sure that the controller has a parameterless public constructor."}
Edited testController:
public class TestController : Controller
{
private readonly ITestService _testService;
public TestController(ITestService service)
{
_testService = service;
}
// GET: Test
[HttpGet]
public ActionResult Index()
{
var test = new TestModel();
test.Greeting = "yo" + _testService.GetString();
test.Name = "nils";
return View(test);
}
}
You're injecting your dependency into your action method.
When using IDependencyResolver in this manner you tend to inject dependencies into your constructor.
Try changing controller to look something like this:
public class TestController : Controller
{
private readonly ITestService service;
public TestController(ITestService service)
{
this.service = service;
}
// GET: Test
[HttpGet]
public ActionResult Index()
{
var test = new TestModel();
test.Greeting = "yo";
test.Name = "nils";
// TODO do something with ITestService
// this.service.DoSomethingCool()
return View(test);
}
}
Declare it like this :
public class TestController : Controller
{
private ITestService service;
public TestController(ITestService service)
{
this.service = service;
}
// GET: Test
[HttpGet]
public ActionResult Index()
{
var test = new TestModel();
test.Greeting = "yo";
test.Name = "nils";
return View(test);
}
}
Please inject your dependencies inside your constructor. You by mistake passed it to your action method.

How to inject multiple dependencies in constructor?

I am doing unit testing.And i have a controller which is depended on multiple repositories(means there are multiple dependencies).
Below is the piece of code of controller :-
public class TestController : BaseController
{
//Declaring dependencies
private IProductService _productService;
private IStudenctService _studentService;
private ITeacherService _teacherService;
private IClassService _classService;
private ITaxService _taxService;
private ICategoryService _categoryService;
private ISchoolService _schoolService;
//Constructor calling…
public TestController ()
{
}
public TestController (IProductService productService)
{
this._ productService = productService;
}
public TestController (IStudenctService studenctService)
{
this._ studentService = studenctService;
}
public TestController (ITeacherService teacherService)
{
this._ teacherService = teacherService;
}
public TestController (IClassService classService)
{
this._ classService = classService;
}
public TestController (ITaxService taxService)
{
this._ taxService = taxService;
}
public TestController (ICategoryService categoryService)
{
this._ categoryService = categoryService;
}
public TestController (ISchoolService schoolService)
{
this._ schoolService = schoolService;
}
public TestController (ISchoolService schoolService, ICategoryService categoryService)
{
this._ schoolService = schoolService;
this._ categoryService = categoryService;
}
public TestController (ISchoolService schoolService, ICategoryService categoryService, ITaxService taxService, IClassService classService) {
this._ schoolService = schoolService;
this._ categoryService = categoryService;
this._ taxService = taxService;
this._ classService = classService;
}
}
In the above code i have made separate constructor for each dependencies.Where there 2 constructor taking multiple arguments(dependency arg).
By this my unit test method is working well. But when i run application then its giving me below error :-
Uh-oh, something went wrong! Error Code: 500
But when i call only one parameter constructor then its working.Can anyone let me know what is wrong here ? What should do in case of multiple dependencies ?
If these are dependencies of your class, then you should have a single constructor that takes all of the dependencies as parameters.
In other words, you can not instantiate to a valid state without all of your dependencies. They are not optional, they are dependencies.
I would start with taking this approach, and then ask a separate question if your application still throws an error.

Categories

Resources