I'm working on web application project which uses ASP.NET Core 2.1. Along with developing the API we are also trying to Unit test it using MSTest framework.
My Controllers are inheriting from ControllerBase. In my Test Bench I'm mocking my Business Layer using Moq Framework. When I'm calling the Controller from the test method, I need to pass a Mocked Business instance to the controller, for which I'm trying to declare parameterized constructor.
It's working fine for test cases, but my normal flow is disturbed. I even tried using both parameterized and parameterless constructors.
This works fine with Dot Framework which inherits APIController.
public class BookingController: ControllerBase {
BusinessManager business = new BusinessManager();
//Non-Parameterized Constructor
public BookingController() {}
//Parameterized Constructor
public BookingController(BusinessManager mockedBusiness) {
this.business = mockedBusiness;
}
}
A non-parameterized constructor should be used when called from UI.
Parameterized should only work when called from Test Bench passing some instance.
In the original code, the
BusinessManager business = new BusinessManager();
was tightly coupling the controller to the dependency, and is considered a code smell. Which is why you ended up having to try a work around in order to be able to test the controller in isolation.
Use the explicit dependency principle and keep the parameterized constructor
public class BookingController: ControllerBase {
private readonly BusinessManager business;
//Parameterized Constructor
public BookingController(BusinessManager business) {
this.business = business;
}
//...
}
In Startup, register you dependency with the service collection
public void ConfigureServices(IServiceCollection services) {
//...
services.AddScoped<BusinessManager>();
//...
}
The will allow the framework to inject the required dependency at run time when the controller is created in your normal flow, and also allows the controller to be flexible enough to be tested in isolation with your mocked business instance.
Related
I've just come from a place where an API controller would have just the Services it needed injected in to it...
[ApiController]
public class SomeController : ControllerBase
{
private IFirstService firstService
private ISecondService secondService
public SomeController(IFirstService firstService, ISecondService secondService)
{
this.firstService = firstService;
this.secondService = secondService;
}
[HttpGet]
public IActionResult SomeMethod()
{
var data = firstService.GetSomething();
return OkObjectResult(data);
}
}
Now I find myself in a shop that does this...
[ApiController]
public class SomeController : ControllerBase
{
private IServiceProvider services;
public SomeController(IServiceProvider services)
{
this.services = services;
}
[HttpGet]
public IActionResult SomeMethod()
{
var service = servies.Get<IFirstService>();
if(service is null)
{
//...
}
var data = firstService.GetSomething();
return OkObjectResult(data);
}
}
Now, I can't really explain why, but this just seems wrong.
Am I just experiencing StuckInMyWaysitis or is this really the bad practice my bones tells me it is? Or, is there, in fact, a more widely accepted way of doing the "right" thing?
Injecting IServiceProvider implements the Service Locator pattern, which is generally considered to be an anti-pattern.
In your first example two services are injected. You can easily tell what the controller depends on. It's easier to tell if a class begins to depend on too many things when we see five, 10, or 20 dependencies injected. When that happens we usually refactor because the number of dependencies indicates that the class is doing too many things.
In the second example we can't tell from the injected dependency (IServiceProvider) what the class depends on. The only way to tell is to look at every use of services throughout the class and see what gets resolved from it. A class could end up depending on many other classes even though we only see one dependency in the constructor.
This also makes unit testing more difficult. In the first example we might have to create fakes or mocks for one or both services. In the second example we have to either mock IServiceProvider to return mocks or create an IServiceCollection, register the mocks with it as service implementations, and then build a ServiceProvider from it. Both make tests more complex.
Some have reasoned that API controllers are an exception, and that it's okay to have them depend on something like a service locator. (MediatR is a common example.) This is an opinion: It's not bad as long as the controller has little or no logic and is only used to route HTTP requests to some higher-level code.
If we use MediatR or some similar abstraction like ICommandHandler<TCommand> then at least we've constrained the class to submitting queries or commands to handlers. It's not as bad as injecting IServiceProvider which allows the class to resolve any registered service.
It's wrong because it means that every time you need a service you have to explicitly request it and then check the instance for null. This is unnecessary code duplication for no benefit.
It also violates the explicit dependencies principle, which Microsoft recommends you use to architect your code.
Almost certainly this was done because somebody couldn't figure out how DI works, or they forgot to register a service and couldn't be a***d to fix it properly, so they just chucked in IServiceProvider instead and that ended up working, and then they cargo-culted it everywhere. In other words, laziness and/or ignorance.
Likely you will come up against resistance when you try to fix this by using explicit dependencies. The trick is to make the person(s) advocating for this mess explain why the mess is better than following good architectural practices, particularly those from Microsoft.
When you've been programming long enough, you learn to trust your gut. If it feels bad, it almost always is.
First, Let us refactor the second code to get rid of some code smells,
[ApiController]
public class SomeController : ControllerBase
{
private IFirstService firstService
private ISecondService secondService
private IServiceProvider services;
public SomeController(IServiceProvider services)
{
this.services = services;
this.firstService= servies.Get<IFirstService>();
this.secondService= servies.Get<ISecondService>();
}
[HttpGet]
public IActionResult SomeMethod()
{
var data = firstService.GetSomething();
return OkObjectResult(data);
}
}
Why?
you automatically get rid of all the checks, and now you can do that in your constructor if needed.
If many methods needed instances all might have duplicate codes like this.
It violates SRP as the methods are doing more than they should be.
Now if we look it is closer to your First code. With one difference, Instantiating service vs Injecting service. There are a few problems with this IMO,
DI Containers are tools, they are not part of our domain. By taking IServiceProvider, we are trying our services to them. Which implies we always need some DI provider.
Secondly this also hides our dependencies, which makes integration
difficult. Constructors are like messengers that clearly tell us
what we need to keep ready beforehand, before we instantiate a
Class. If we hide this information, you may not know if certain
dependency was configured or not without running the application.
With clearly defined dependencies in constructor, we cannot skip
this part.
Also, just like we had duplicate code in our methods, now we have duplicate code in constructor of different services. Each service will be calling these Get methods. So why not do them in one place. And if you consider this and refactor, you automatically reach to your first example.
[ApiController]
public class SomeController : ControllerBase
{
private IFirstService firstService
private ISecondService secondService
public SomeController(IFirstService firstService, ISecondService secondService)
{
this.firstService = firstService;
this.secondService = secondService;
}
}
public class Startup()
{
public void Start()
{
//....
//....
var service1 = servies.Get<IFirstService>();
var service2 = servies.Get<IFirstService>();
SomeController= new Controller(service1,service2);
//or just servies.Get<SomeController>();
}
}
This is how instantiation happen if you use Containers like AutoFac.
I have setup the dependency injection in startup.cs say: IAction. In controller, I can inject the service as a parameter in the constructor. But what if my normal class in Business Layer for example, How do that service be injected.
In Microsoft documentation, it is a bad design if do something like the image below:
Is there a better way? If I tried passed these service from controller to other layers, this will not give good result as well.
You should be able to pass the same dependencies through the constructors of the classes in your business layer just like you pass them through the constructors of your controllers in your Web API layer or MVC layer.
Something like this:
public class UsersService
{
private readonly IUsersRepository usersRepository;
public UsersService(IUsersRepository usersRepository)
{
this.usersRepository = usersRepository;
}
public async Task<User> GetUser(int userId)
{
return await usersRepository.GetByIdAsync(userId);
}
}
In ASP.NET Core MVC all classes that implement Controller will be automatically resolved and added to the MVC pipeline. These controllers can also be injected into the DI container using services.AddMvc().AddControllersAsServices();
I also have a controller that also implements a specific interface, which I can also add to the DI container: services.AddSingleton<IMyInterface, MyImpl>();
public class MyImpl : Controller, IMyInterface { }
However, becase this controller also implements Controller it has already been added in AddControllersAsServices() so adding it to the DI container one more time causes there to be two instances of this class.
The reason for this design is that I will have multiple implementations of IMyInterface and later need to decide which one to use, but each implementation will also need to be a controller in order to provide certain API endpoints (each controller will provide different endpoints, so there will be no conflicts there).
How can I ensure that only one instance of my class is instantiated, and how can I then get all implementations of IMyInterface?
As much as Im concerned Controller class is instantiated on each request, so even if you specify something like this (Ninject style):
services.Bind<IMyInterface, MyController>().To<MyController>().InSingletonScope();
It will be very bad. I mean, Controller is statefull, and you just mix everything up and breaking it's internal context.
What you might do is decorate through controller, instead of managing its lifetime yourself:
public class MyImpl : IMyInterface
{
}
public class MyController : Controller
{
private readonly IMyInterface _inner; //delegate implementation to this one.
public MyController(IMyInterface inner)
{
_inner = inner;
}
}
And injection:
services.Bind<IMyInterface>().To<MyImpl>().InSingletonScope();//this is your logic.
sercices.Bind<MyController>().ToSomethingWhatever();//this line is managed by ASP .NET, mentioned this only to show the idea
You might need remove the MyImpl inheriting from Controller class. Also you need to consider MyImpl as sevice rather than Controller.
Another option is that this can be achieved with IoC container like Autofac or Ninject or Castle Windsor. When using with Autofac it will be something like the below
Add the Autofac, Autofac ASP.Net MVC4 Integration using NuGet Package
Open GLobal.asax.cs
Make following changes in the Application_Start().
3a. Comment out the below code as
//WebApiConfig.Register(GlobalConfiguration.Configuration);
3b. Create a new method RegisterAutofac(), call this as the first method call inside Application_Start()
3c. Below with the sample implementation for RegisterAutofac() method
private void RegisterAutofac()
{
var builder = new Autofac.ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterSource(new ViewRegistrationSource());
// The object to be injected in constructor etc.
builder.RegisterType<MyImpl>().As<IMyInterface>().SingleInstance();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
I am sure there are answers on here to my question, though I just don't either quite understand what I'm looking for or what I'm reading... Also, not 100% sure DI is what I should be using in this case.
I am attempting to use Unity for my DI. I am injecting dependency into ASP.Net Web API Controllers. And so far so good.
I am injecting Services into my controllers that the controller will require. For example, in one of my controllers I have:
private TransactionService _transactionService;
public TransactionsController(TransactionService transactionService)
{
_transactionService = transactionService;
}
In this case I am injecting an instance of TransactionService into the controller. This is all working.
My WebApiConfig.cs contains the following, which as i understand it actually performs the injection:
var container = new UnityContainer();
container.RegisterType<ServiceBase>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
I can show you my UnityResolver if needed.
Now the part I'm struggling with...
My services all inherit from an Abstract class ServiceBase - in its simplest for it looks like this:
public abstract class ServiceBase : IDisposable
{
internal Account _account;
public ServiceBase(){}
}
What I would like to do is create the Account during my injection process and pass it in somehow so that my injected services don't need to deal with instansiating the account.
The moment I try adding any constructors to my services to accept an Account I receive the message to ensure my controllers have a parameterless constructor.
So.. how do i set up my DI so that I can inject services into my controllers and also inject a pre-instantiated instance of Account into my services?
Update
I forgot to mention (sorry Wiktor) - I would like to NOT use Attributes if possible. It seems strange in my mind that we can use DI to unhook dependency and then go and put a bunch of dependent attributes everywhere. I quite possibly just don't understand the DI concept correctly, though this doesn't seem right to me
That should be simple, just make the additional property public and add the dependency attribute on it.
[Dependency]
public Account _account { get; set; }
Unity should be able to inject the attribute and you can even register the Account class in an ordinary way (for example with an injection factory).
I hope this would give some idea for you.
Create an interface for service base and declare Acccount as public property.
Interface for your service:
you can also inherit other interfaces.
public interface ITransactionService : IDisposable
{
IAccount Account{get;set;}
}
Implement it in your class:
public class TransactionService : ITransactionService{
private IAccount _account;
public IAccount Account
{
get
{if(_account==null)_account=new Account(); return _account;}
set
{_account=value;}
}
}
Now use the constructor at API controller as shown below:
private ITransactionService _transactionService;
public TransactionsController(ITransactionService transactionService)
{
_transactionService = transactionService;
}
Unity resolver:
var container = new UnityContainer();
container.RegisterType<ITransactionService,TransactionService>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
So using in this way where property injection and constructor injection used for reducing tightly coupled dependency.
It will be very easy for mocking the interface for unit testing.
You may also create an interface for Account class, so that it could be easy for mocking based on your use.
In case you don't want to use attributes, which I totally agree with, the best approach is to have ServiceBase accept the account parameter, like:
public abstract class ServiceBase {
private Account _account;
public ServiceBase(Account account) {
this._account = account;
}
}
You will have to declare the same constructor on your derived service as well TransactionService. When the controller is instantiated, Unity will correctly create the instance of Account class first and then pass it on to your TransactionService object via constructor injection. And you should register Account object using a life time manager to scope it to singleton.
Hope this helps.
I have a layered application with the following projects:
DAL (using EntityFramework with repositories)
DAL.Model (contains the entities, and is referenced by all the others)
Services
UI (in wpf)
The base repository looks like this:
public abstract class RepositoryBase<T> where T : class
{
private readonly MyContext context;
private readonly IDbSet<T> dbSet;
protected RepositoryBase(MyContext dataContext)
{
context = dataContext;
dbSet = context.Set<T>();
}
protected MyContext Context
{
get { return context; }
}
**And a series of virtual methods for Add, Delete, etc.
}
All repositories extend this one, such as:
public class MarketRepository : RepositoryBase<Market>
{
public MarketRepository(MyContext dataContext) : base(dataContext)
{
}
public IEnumerable<Market> GetAllMarkets()
{
return this.Context.Markets.ToList<Market>();
}
}
The services look like this:
public class MarketService
{
IMarketRepository _marketRepository;
public MarketService(IMarketRepository marketRepository)
{
_marketRepository = marketRepository;
}
public IEnumerable<Market> GetAllMarkets()
{
return _marketRepository.GetAllMarkets();
}
}
What I would like to achieve is that the UI layer would only have a reference to the Services layer, the Services layer only with the DAL layer (and all of them to Model, where the entities live) using DI (right now I'm using Unity).
The problem is, in my container in the UI I only want to do this
unity.RegisterType<IMarketService, MarketService>();
and not have to do it as well for the repositories, because then the UI layer would have a dependency on the DAL layer.
I thought about adding a parameterless constructor to the Service classes, like:
public MarketService() : this(new MarketRepository(*What would I put here?)) { }
but then I'm loosing the abstraction that the interface gives, and also I don't know what to do with the MyContext that the repository needs as a parameter; if I pass a new one, then I need to reference the DAL.
Should I change my repositories to create a new MyContext in the constructor, rather than getting it as a parameter?
How can I refactor my architecture to make it work properly and with minimal dependencies?
Well, I belive it is up to the bootstrapper to configure dependencies, in the higher level of the application. As it is usually the UI project, if it needs to reference other assemblies, so be it. If you do not like your UI project managing that, than create a bootstrapper project responsable for getting your app running and separete your UI classes in another one.
Your IoC container should support Dependency Injection using a string from an external configuration file. This way you are not hardcoding the mapping. Structuremap does this quite well, so I am sure other IoCs will.
Adding external dependenices as a parameter when creating an instance is the way to go.
I think you should make yourself more familiar with the different ways to configure Unity, so that the dependencies are resolved.
Could you elaborate why you are creating a repository when using a dependency injection framework?
When configuring DI, you should follow the same pattern - UI bootstrapper initializes Services, Services initialize DAL. (With autofac or ninject you could achiece this using modules. With unity you should emulate modules).
In pseudocode something like
//ui
void UILayer.ConfigureUnity(unity)
{
ServiceLayer.ConfigureUnity(unity)
}
//services
void ServiceLayer.ConfigureUnity(unity)
{
DAL.ConfigureUnity(unity)
unity.RegisterType<IMarketService, MarketService>();
}
//dal
void DAL.ConfigureUnity(unity)
{
unity.RegisterType<IMarketRepository, MarketRespository>();
unity.RegisterType<MyContext, MyContext>(); //not sure exact syntax - just register type for 'new Type()' activator.
}