How to inject multiple dependencies in constructor? - c#

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.

Related

How to resolve dependency in integration test Asp.Net MVC

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);
}
}

Use Inversion of Control to construct dependency with caller

Given the following ASP.NET Core controller :
public class MyController : Controller {
public MyController(IDependency dependency) { this.dependency = dependency; }
}
public interface IDependency;
public class DependencyImplementation : IDependency {
public DependencyImplementation(Controller controller) { ... }
}
I want MyController to have a new instance of DependencyImplementation injected, constructed with the controller it's being passed to. Ideally using Ninject.
The non-IoC version would be:
public class MyController : Controller {
public MyController() { this.dependency = new DependencyImplementation(this); }
}
This would cause circular dependency. Only idea I have is to introduce factory:
public interface IDependencyFactory
{
IDependency Create(Controller controller);
}
public class MyController : Controller
{
private IDependency dependency;
public MyController(IDependencyFactory dependencyFactory)
{
this.dependency = dependencyFactory.Create(this);
}
}
var kernel = new StandardKernel();
kernel.Bind<Controller>().To<MyController>();
kernel.Bind<IDependency>().To<DependencyImplementation>();
kernel.Bind<IDependencyFactory>().ToFactory();
var controller = kernel.Get<Controller>();
Or maybe rather reconsider whole design.

BaseController's overloaded constructor not being executed?

public class BaseController : Controller
{
[Inject]
public IUnitOfWork UnitOfWork { get; set; }
private readonly ISomeService _someService ;
public BaseController(ISomeService someService)
{
_someService = someService;
}
public void Contacts()
{
contacts = _someService .GetById(1);
ViewBag.someThing = contacts; //Add whatever
}
public BaseController()
{
}
}
While I'm sending someService in the :base I can get the data from it. However I don't want to send someService from each controller like AboutController to the BaseController and to write too much code.
public class HomeController : BaseController
{
private readonly ISomeService someService;
public HomeController(ISomeService someService) : base(someService)
{
_someService = someService;
}
}
public class AboutController : BaseController
{
private readonly IAboutService _aboutService;
public AboutController (IAboutService aboutService)
{
_aboutService = aboutService;
}
}
So in AboutController view still i wanna get someService's data without sending parameter to the BaseController
The short answer would be separated in two cases:
If you want to use ISomeService from the base controller you are obliged to pass that service through base constructor like this:
public class AboutController : BaseController
{
private readonly IAboutService _aboutService;
public AboutController (IAboutService aboutService, ISomeService someService) : base(someService)
{
_aboutService = aboutService;
}
}
If you dont want to use that service you use the default base constructor like this otherwise it will be null if you try to access it:
public class AboutController : BaseController
{
private readonly IAboutService _aboutService;
public AboutController (IAboutService aboutService) : base()
{
_aboutService = aboutService;
}
}
You are in the first scenario so you need to pass it through the constructor in order to initialize it!
But if you like to break the pattern you would choose other ways of injecting the services into your base controller:
First one by using auto-properties:
For example:
public ISomeService SomeService { get; set;}
Another way is to get the instance of the service by using DependecyResolver but this would 'break' somehow the DI pattern and it will make harder for testing etc. But if you choose to do so here is the code for that:
public class BaseController : Controller
{
[Inject]
public IUnitOfWork UnitOfWork { get; set; }
private readonly ISomeService _someService ;
public BaseController(ISomeService someService)
{
_someService = someService;
}
public void Contacts()
{
contacts = _someService .GetById(1);
ViewBag.someThing = contacts; //Add whatever
}
public BaseController()
{
_someService = DependencyResolver.Current.GetService<ISomeService >();
}
}
For more info refer to this question here

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.

Calling super constructor in C#

I have classes such as AccountsController, ProductsController etc that all inherit from BaseController. Unity sets up my services as needed. These classes also all require a _sequence service. As it is a common requirement for all classes I would like to code this in the BaseController.
public class AccountsController : BaseController
{
public AccountsController(
IService<Account> accountService) {
_account = accountService;
}
public class ProductsController : BaseController
{
public ProductsController(
IService<Account> productService) {
_product = productService;
}
public class BaseController : Controller
{
public IService<Account> _account;
public IService<Product> _product;
protected ISequenceService _sequence;
public BaseController(
ISequenceService sequenceService) {
_sequence = sequenceService;
}
But how can I do this? Should I set up a call to the BaseController inside the constructors of each of the AccountsController and ProductsController?
You can chain constructors:
public class ProductsController : BaseController
{
public ProductsController(
IService<Account> productService) : base(productService)
{
_product = productService;
}
}
Note that the chained BaseController (using the base keyword) has been passed the productService parameter, tough this can be anything.
Update:
You could do the following (poor mans' dependency injection):
public class ProductsController : BaseController
{
public ProductsController(
IService<Account> productService) : base(new SequenceService())
{
_product = productService;
}
}
Or, pass in the dependency on ISequenceService through your inheriting types:
public class ProductsController : BaseController
{
public ProductsController(
IService<Account> productService, ISequenceService sequenceService)
: base(sequenceService)
{
_product = productService;
}
}

Categories

Resources