The situation I have is this:
DbContext
calls are made from the controller layerDbContext
is wrapped in a using statement and instantiated as necessary for memory management purposes NOT connection pool purposesDbContext
into the controller.Conditions I can change:
So, my question is this: how do I pass in a DbContext
to the constructor so I can mock the responses being returned, but maintain the reliability of the using statement, as these tend to contradict each other.
I'm ok if I need to stop using the using
statement, as long as there is a way to ensure that the context is disposed every time when it is done performing the requested action.
Any thoughts on this one?
Constructing a DbContext inside a method you'd like to test is no different than instantiating any other concrete instance of a dependency within the code, it means you cannot test with a mocked dependency. So the immediate options that come to mind are (without code/structure changes):
Mocking a DbContext is messy, but do-able. Once you have one mock-able I would recommend adding an IoC container like Autofac into the project. I don't know the circumstances that would prevent you from introducing an IoC container, but if the team is worried about it being an all-or-nothing re-factor and too big of a job, then I'd reassure them that it can be added with minimal changes to the project and in a way that does not break existing code. Aside from the DbContext, if the code isn't using DI/IoC Container, how do you plan to handle other concrete dependencies? You don't have to switch out all dependencies/controllers in one go, but improve them incrementally.
Once a container is set up to resolve MVC Controllers, existing controllers with default constructors will not be affected. You can then register your DbContext with the container, and adjust your controller under test to accept the context in the constructor. The IoC Container would set up the DbContext lifetime scope to Instance per Request for example, so you don't need the using {}
block. From there your tests can provide the mocked DbContext, while The container manages the Context lifespan.
Regarding making unit-test friendly controllers/code with an IoC container I'd recently posted an article on the use of Lazy dependencies /w Autofac to make writing tests for classes with multiple dependencies a snap. You can have a read at https://medium.com/@StevePy/writing-easily-testable-code-with-autofac-lazy-properties-f9c63457c8ce