Why inject the entire DbContext instead of just the necessary DbSets? - c#

I've seen a lot of projects whether the entire DbContext is injected in a class:
public class MyClass
{
public MyClass(MyDbContext context)
{
...
}
public void DoStuff()
{
dbContext.MyTable.Select(x => x...)
}
}
Why not do this:
public class MyClass
{
public MyClass(DbSet<MyType> myTypes)
{
...
}
public void DoStuff()
{
myTypes.Select(x => x...)
}
}
I find #2 makes it more clear as to what data exactly the object needs to operate. It makes unit testing especially more clear as the dependencies are obvious from the constructor. Otherwise, you have to inspect the implementation of the method to find out what data it needs exactly so you can setup your test properly.
So why is #1 the norm?
(P.S. sorry for bad tags but it seems the tag system is broken atm)

Normally developers write unit tests to test business use cases and the data access layer should not contain any logic and that's why people use Repository Pattern to hide the implementation of the data access layer.
Otherwise, you have to inspect the implementation of the method to
find out what data it needs exactly so you can setup your test
properly.
MyDbContext and DbSet<MyType> are related to data access and when you try to implement unit tests for DoStuff method, you should not consider the implementation of query for writing test and the only thing you need is mocking MyDbContext or DbSet<MyType>. Also when use concrete class as a dependency, you violate Dependency Inversion Principle, and that is why you have to look at the implementation of DoStuff method to find out what data and where the data comes from.

Because the "Save" is on the dbcontext, not the child collections.
"SaveChangesAsync" as the most important one. But others listed below.
int saveChangesAsyncValue = await this.myDbContext.SaveChangesAsync(token);
Framework:
https://learn.microsoft.com/en-us/dotnet/api/system.data.entity.dbcontext.savechangesasync?view=entity-framework-6.2.0
Core:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.savechangesasync?view=efcore-5.0
Others (core):
https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.savechanges?view=efcore-5.0
You should really focus having unit tests on your BUSINESS LOGIC. And subtly, this also means.
Stop putting (any) business logic in your data layer. (and its kissing cousin, stop putting business logic in your presentation layer).
You should inject a (mock) of your datalayer into your business logic classes.
Having said that, EF InMemoryDatabase has blurred the lines a little bit.
But that does not avoid having to have the "myDbContext" available.

Related

Dependency injection further down the "chain"

I've been reading up on how to write testable code and stumbled upon the Dependency Injection design pattern.
This design pattern is really easy to understand and there is really nothing to it, the object asks for the values rather then creating them itself.
However, now that I'm thinking about how this could be used the application im currenty working on I realize that there are some complications to it. Imagine the following example:
public class A{
public string getValue(){
return "abc";
}
}
public class B{
private A a;
public B(A a){
this.a=a;
}
public void someMethod(){
String str = a.getValue();
}
}
Unit testing someMethod () would now be easy since i can create a mock of A and have getValue() return whatever I want.
The class B's dependency on A is injected through the constructor, but this means that A has to be instantiated outside the class B so this dependency have moved to another class instead. This would be repeated many layers down and on some point instantiation has to be done.
Now to the question, is it true that when using Dependency Injection, you keep passing the dependencys through all these layers? Wouldn't that make the code less readable and more time consuming to debug? And when you reach the "top" layer, how would you unit test that class?
I hope I understand your question correctly.
Injecting Dependencies
No we don't pass the dependencies through all the layers. We only pass them to layers that directly talk to them. For example:
public class PaymentHandler {
private customerRepository;
public PaymentHandler(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
public void handlePayment(CustomerId customerId, Money amount) {
Customer customer = customerRepository.findById(customerId);
customer.charge(amount);
}
}
public interface CustomerRepository {
public Customer findById(CustomerId customerId);
}
public class DefaultCustomerRepository implements CustomerRepository {
private Database database;
public CustomerRepository(Database database) {
this.database = database;
}
public Customer findById(CustomerId customerId) {
Result result = database.executeQuery(...);
// do some logic here
return customer;
}
}
public interface Database {
public Result executeQuery(Query query);
}
PaymentHandler does not know about the Database, it only talks to CustomerRepository. The injection of Database stops at the repository layer.
Readability of the code
When doing manual injection without framework or libraries to help, we might end up with Factory classes that contain many boilerplate code like return new D(new C(new B(), new A()); which at some point can be less readable. To solve this problem we tend to use DI frameworks like Guice to avoid writing so many factories.
However, for classes that actually do work / business logic, they should be more readable and understandable as they only talk to their direct collaborators and do the work they need to do.
Unit Testing
I assume that by "Top" layer you mean the PaymentHandler class. In this example, we can create a stub CustomerRepository class and have it return a Customer object that we can check against, then pass the stub to the PaymentHandler to check whether the correct amount is charged.
The general idea is to pass in fake collaborators to control their output so that we can safely assert the behavior of the class under test (in this example the PaymentHandler class).
Why interfaces
As mentioned in the comments above, it is more preferable to depend on interfaces instead of concrete classes, they provide better testability(easy to mock/stub) and easier debugging.
Hope this helps.
Well yes, that would mean you have to pass the dependencies over all the layers. However, that's where Inversion of Control containers come in handy. They allow you to register all components (classes) in the system. Then you can ask the IoC container for an instance of class B (in your example), which would automatically call the correct constructor for you automatically creating any objects the constructor depends upon (in your case class A).
A nice discussion can be found here: Why do I need an IoC container as opposed to straightforward DI code?
IMO, your question demonstrates that you understand the pattern.
Used correctly, you would have a Composition Root where all dependencies are resolved and injected. Use of an IoC container here would resolve dependencies and pass them down through the layers for you.
This is in direct opposition to the Service Location pattern, which is considered by many as an anti-pattern.
Use of a Composition Root shouldn't make your code less readable/understandable as well-designed classes with clear and relevant dependencies should be reasonably self-documenting. I'm not sure about unit testing a Composition Root. It has a discreet role so it should be testable.

Unit test a method which is on high abstraction level

A similar topic has been discussed in The value of high level unit tests and mock objects
However, I'd like to describe a specific situation and ask your opinion about how I should write a unit test.
I am developing an ordinary 3-tier application, which uses Entity Framework. Above EF, I have two layers:
Repositories: They directly access the EF ObjectContext and do all the CRUD work (actually, these classes are generated with a T4 template). All Repository class has an appropriate interface.
Managers: They implement the higher level business logic, they do not access directly the ObjectContext, rather use an appropriate Repository. Managers do not know the concrete Repository-implementation, only the interface (I use dependency injection, and mocks in the unit test).
Without further description, here is the class I'd like to write unit tests for:
public class PersonManager
{
private IPersonRepository personRepository; // This is injected.
// Constructor for injection is here.
public void ComplexMethod()
{
// High level business logic
bool result = this.SimpleMethod1();
if(result)
this.SimpleMethod2(1);
else
this.SimpleMethod2(2);
}
public bool SimpleMethod1()
{
// Doing some low-level work with the repository.
}
public void SimpleMethod2(int param)
{
// Doing some low-level work with the repository.
}
}
It is really easy to unit test SimpleMethod1 and SimpleMethod2 by instantiating the PersonManager with a mock of the PersonRepository.
But I can not find any convenient way to unit test ComplexMethod.
Do you have any recommendation about how should I do that? Or that should not be unit tested at all? Maybe I should not use the this reference for the method calls in ComplexMethod, rather access the PersonManager itself via an interface, and replace that with a mock too?
Thanks in advance for any advice.
Guillaume's answer is good (+1), but I wanted to give an additional observation. What I see in the code you've posted is the basis for a very common question from people trying to figure out (or argue against) TDD, which is:
"How/why should I test ComplexMethod() since it depends on SimpleMethod1() and SimpleMethod2(), which are already tested and have their own behavior that I'd have to account for in tests of ComplexMethod()? I'd have to basically duplicate all the tests of SimpleMethod1() and SimpleMethod2() in order to fully test ComplexMethod(), and that's just stupid."
Shortly after, they usually find out about partial mocks. Using partial mocks, you could mock SimpleMethod1() and SimpleMethod2() and then test ComplexMethod() using normal mock mechanisms. "Sounds great," they think, "This will solve my problem perfectly!". A good mock framework should strongly discourage using partial mocks in this way, though, because the reality is:
Your tests are telling you about a design problem.
Specifically, they're telling you that you've mixed concerns and/or abstraction levels in one class. They're telling you that SimpleMethod1() and SimpleMethod2() should be extracted to another class which this class depends on. No matter how many times I see this scenario, and no matter how vehemently the developer argues, the tests are proven right in the end 100% of the time.
I don't see what the problem is. You can test your complex method while mocking the repository, there is no problem.
Your would need two unit-tests, each one would use the same sequence of expectations and executions that you have in your tests of the SimpleMethod1 (I assume you already have two unit-tests for SimpleMethod1, one for a return of "true", one for "false") and also the same expectations that you have for your test SimpleMethod2 with a fixed parameter 1, or 2 respectively.
Granted, there would be some "duplication" in your testing class, but that's not a problem.
Also note your tests for SimpleMethod2 should not make any assumption for the parameter passed: in "real-life" you can have only 1 or 2 as a parameter (and that's what your unit-test for ComplexMethod would have), but your unit-tests for SImpleMethod2 should test it whatever the parameter is: any int.
And finally, if ComplexMethod is the ONLY way to call SimpleMethod1 and/or SimpleMethod2, you should consider making these private, and have only unit-tests for ComplexMethod.
Does that make sense?

I know how to use dependency injection but I recognize no practical advantage for it

It is about this (Inject the dependency)
private readonly ICustomerService _customerService;
public Billing(ICustomerService customerService)
{
_customerService = customerService;
}
versus this (Create the dependency)
private readonly ICustomerService _customerService;
public Billing()
{
_customerService = new CustomerService();
}
The latter sample so they say is bad because... it violates DI...of course nothing is injected... but what if DI would not exist, what is so bad that the CustomerService is created manually from the Billing class? I see no practical advantage concerning exchangeability of the Service interface.
I ask for a practical example with source code may it be a unit test or showing a practical solution why it is so much more loose coupling.
Anyone keen enough to show his DI muscles and why it has a practical right to exist and be applied?
UPDATE
So people have not to read all up I will write here my short experience:
DI as a pattern has a practical usage. To follow DI by not injecting all services manually (a poor mans DI tool so they say...) use a DI framework like LightCore/Unity but be sure you use the right tool for the appropriate job. This is what I did not;-) Developing a mvvm/wpf application I have other requirements the LightCore/Unity tool could not support they even were a barrier. My solutions was to use MEFEDMVVM with which I am happy. Now my services are automatically injected at runtime not at startup time.:-)
Understanding the how and understanding the why are very different things..
One of the biggest benefits of DI is for unit testing. In your second example it's impossible to unit test Billing without also testing CustomerService (and also testing any further dependencies in the chain). In that case you're not unit testing, you're integration testing! If you want a good rationale for using DI, you need not look any further than a rationale for unit testing..
Imagine that CustomerService connects to your CRM system and your database. It creates a whole bunch of network connections to retrieve data about the customer and maybe reads additional things from the database to augment that before returning the data to the Billing class to use in its calculation.
Now you want to unit test Billing to make sure the calculations it's making are correct (you don't want to send out wrong bills right?)
How will you unit test Billing if its constructor is tied to a class that requires connections to a real CRM system and database? Wouldn't it be better to inject that dependency as an interface, easily allowing you to provide a mock version for your tests?
That is why DI is useful.
DI Comes in useful, when you want to pass different implementations of the Interface to your class, for example: Unit Testing.
Say your Billing constructor is an MVC controller's constructor, and your CustomerService took some form of IDataContext as a parameter.
Global.asax
// Does the binding
ICustomerService binds to CustomerService
IDataContext binds to EntityFrameworkContext
CustomerService
private IDataContext _datacontext;
public CustomerService(IDataContext dataContext)
{
_dataContext = dataContext;
}
public AddCustomer(Customer entity)
{
this._dataContext.Customers.Add(entity);
this._dataContext.SaveChanges;
}
MVC Controller
private ICustomerService _customerService;
public Billing(ICustomerService customerService)
{
_customerService = customerService;
}
public ActionResult NewCustomer()
{
Customer customer = new Customer(){ Name = "test" };
this._customerService.AddCustomer(customer);
return View();
}
Say you wanted to unit test your Services, or Controllers. You would pass in the CustomerServices, but you would pass in a fake implementation of the EntityFrameWorkContext.
So a FakeDbContext, that implements IDataContext, is passed to customer services.
The FakeDbContext may just store the entities in Lists or a more elaborate storage mechanism, the point being, you can inject different implementations of dependencies, which allows you to alter the behaviour of one component without having to modify your code elsewhere.
In my experience it is not only about avoiding integration test (but that is a very important point too). Instantiating classes on the inside can create a lot of work unit testing. A class like CustomerService might depend on an open Database connection, configuration files, services being available and a lot of other stuff, that you should not have to know about, when your job is to test the Billing class only.
That being said, sometimes it is a pain always to inject everything. Injection frameworks might lighten that load, but I'm not at big fan. Another kind stackoverflow user pointed me to what he called "poor mans injection". Basically it consists of two constructor overloads: One constructor with the injected interface, and one without. The one without does nothing but instantiate a concrete class that implements the interface, and pass it to the other constructor. It goes something like this:
public class Billing
{
ICustomerService _customerService;
public Billing():this(new CustomerService()) {}
public Billing(ICustomerService customerService)
{
_customerService = customerService;
}
}
This way you have an way to inject when testing AND a way to construct the class with a default implementation of the interface. Not everybody loves this pattern, but I find it practical for some scenarios.

Is Typemock the only framework that can mock a Linq To SQL Table class?

I am trying to setup unit tests for my Linq To SQL code. My code uses the System.Data.Linq.Table class (generated by the designer).
Because this class is sealed and the constructor is internal it is completely impervious to unit testing frameworks like Rhino Mocks. (Unless you want to alter you code to use the repository pattern, which I would rather not.)
Typemock can (some how) mock this class. (See here for an example.)
However, Typemock is also $800 a license. I don't see my employer springing for that anytime soon.
So here is the question. Are there any other mocking frameworks out there that don't rely on Interfaces to create the mocks?
Edit: Example of code that I need to test:
public class UserDAL : IUserDAL
{
private IDataClassesDataContext _ctx;
public UserDAL()
{
string env = ConfigurationManager.AppSettings["Environment"];
string connectionString = ConfigurationManager
.ConnectionStrings[env].ConnectionString;
_ctx = new DataClassesDataContext(connectionString);
}
public UserDAL(IDataClassesDataContext context)
{
_ctx = context;
}
public List<User> GetUsersByOrganization(int organizationId)
{
IOrderedQueryable<User> vUsers =
(from myUsers in _ctx.Users
where myUsers.Organization == organizationId
orderby myUsers.LastName
select myUsers);
return vUsers.ToList();
}
public bool IsUserInOrganization(User user, int orgainzationID)
{
// Do some Dal Related logic here.
return GetUsersByOrganization(orgainzationID).Contains(user);
}
}
I have shorted this up to make it easier to read. The idea is that I have some code (like IsUserInOrganization that calls another method (like GetUsersByOrganization) that does a Linq query.
I would like to unit test the IsUserInOrganization method. Do do that I would need to mock _ctx.Users which is a Table class (that is sealed and has an internal constructor).
Check out Microsoft Stubs that has the simple premise of:
Replace any .NET method with your own
delegate!
And a more detailed description of it's capabilities (emphasis is mine).
Stubs is a lightweight framework for
test stubs and detours in .NET that is
entirely based on delegates, type
safe, refactorable and source code
generated. Stubs was designed provide
a minimal overhead to the Pex white
box analysis, support the Code
Contracts runtime writer and
encourage the programmatic models
rather than record/replay tests.
Stubs may be used on any .NET method, including non-virtual/static
methods in sealed types.
There are two standard unit testing approaches in this case:
1) Don't test the platform - if the dependency is on a framework class, you don't write tests where that interaction is verified. This typically means you substitute a dependency at test time, but in your case it likely means you inject the table itself.
2) Wrap the platform - if you need to test something that interacts with the platform, then write a wrapper layer for the relevant components
There's also integration and acceptance testing to consider. For both of these cases you would usually simply accept the dependency as it exists in your application.
What precisely are you concerned about testing that you need to directly mock/substitute this class?
Edit:
It seems as if you're looking to avoid rewriting code to be more testable. This is where TypeMock excels, and is the reason why some test advocates think TypeMock can lead to problems. It is, however, the right tool for the job if you absolutely refuse to restructure your code for testability.
Edit #2:
Perhaps I'm being overly obsessive about this, but let's consider a more testable pattern:
Organization()
{
HasUser(name)
}
OrganizationDAL
{
Organization LoadOrganization(id)
}
OrganizationServiceFacade
{
IsUserInOrganization(name, orgid)
{
return OrgDAL.LoadOrganization(id).HasUser(name)
}
}
Organization's natural contains test for a user no longer needs to be platform-dependent, you should be able to inject the datasource. OrganizationDAL is only responsible for loading organizations rather than returning information about organizations (although there are ways to put queries into this layer if necessary). OrganizationServiceFacade is only responsible for providing composed services, which should both satisfy mockability and avoid the need for extra unit tests (it's an Integration or possibly even an Acceptance target) since it's a wrapper class. Depending on how you construct Organizations, you can inject data without relying on a particular notion of how that data works.
You may want to consider using the Repository pattern, basically it's the "wrap the platform" suggestion from Mike. With it you'll be mocking IRepository rather then the DataContext.
http://blogs.microsoft.co.il/blogs/kim/archive/2008/11/14/testable-data-access-with-the-repository-pattern.aspx

How to test Repository Pattern with ADO.NET Entity Framework?

While using Repository pattern I find it difficult to understand the reason of designing the software with TDD technique while in reality you will have to implement the Interface for your repository in your persistence dataset.
To make my point clear I will submit an example:
I have the following Interface on my domain model:
public interface IUserRepository
{
IQueryable<User> FindAllUsers();
void AddUser(User newUser);
User GetUserByID(int userID);
void Update(User userToUpdate);
}
I have the following implementation of the interface for testing purposes:
public class FakeUserRepository : IUserRepository
{
private IList<User> _repository;
public FakeUserRepository()
{
_repository = new List<User>();
... //create all users for testing purposes
}
public IQueryable<User> FindAllUsers()
{
return _repository.AsQueryable<User>(); //returns all users
}
Now I create a few tests:
Can_Add_User
Can_Add_Account for a User
Can_Add_ShareSpace for a an account of a user with another user.
My question is, after I test all these with my FakeUserRepository implementation, I have to go back and implement the IUserRepository on my actual persistence dataset (i.g. SQL), and I have to implement again the code, so my unit testing is not actually checking the code that I am actually using on my application.
Maybe I am missing something.
Thanks as always!
Below then my Persistent data access repository which is the one that is supposed to be under test (by my mind at least), but then I should not test hooked to the database:
public class SQLUserRepository : IUserRepository
{
private BusinessDomainModel.EntityModel.BusinessHelperAccountDBEntities _repository;
public SQLUserRepository()
{
_repository = new BusinessHelperAccountDBEntities();
}
#region IUserRepository Members
public IQueryable<User> FindAllUsers()
{
return _repository.UserSet.AsQueryable();
}
Never test a mock. The class under test should always be a real instance of the class, though you can and should mock any of its dependencies so you can test it in isolation.
I'll explain what I'm doing, why and how much milage I get out it.
First, I'm doing exactly what you are doing, regarding your repositories. Despite some namespace differences, this is what I also do:
MyProject.Repositories.IUserRepository
MyProject.Repositories.Fake.UserRepository
MyProject.Repositories.SqlServer.UserRepository
With my fake UserRepository, I also just create and populate a private IEnumerable<User> collection (which is a List<User>). Why do I have this? I use this repository for my initial day to day development (because it's fast -> no db access == quick!). Then i swap over the fake respitories for the sql repositories (ie chage my dependency injection (oooohhh!)). This is why this class/namespace exists, as opposed to using Mocks in my unit test for 'fake' stuff. (That happens, but under different circumstances).
With my sql server UserRepository, I use LinqToSql. With regards to you question, it's irrelivant that I'm using LinqToSql ... it could be any other database wrapper. The important thing here is that there's a 3rd party something which i'm integrating with.
Ok, so from here, I need to make sure of two things
The fake UserRepostiory works
The sql server UserRepository works.
First up, most people don't create a unit test for a fake thing. It's a fake piece of turd, so why waste the energy? True --- except that I use that fake piece of turd in my day to day development (refer to my blarg about this, above). So i quickly whip up a few basic unit tests. NOTE: In my eyes these are unit tests, even though they are repository classes. Why? They aren't intergrating with a 3rd party/infrastructure.
Next (finally I get to the point), I do a seperate test class which is an Intergration Test. This is a unit test that will intergrate with something outside of the system. It could be the real Twitter api. It could be the real S3 Amazon api. Notice i used the word real. That's the key, here. I'm intergrating with a real service OUTSIDE of mine. As such -> it's slow. Anytime i need to leave my computer for some data, it's called intergrating and you automatically assume (and expect) it to be slow.
So here, i'm intergrating with a Database.
(Nae sayers, please don't Troll this with cheeky suggestions that you have the database on the same computer ... you're leaving your APPLICATION 'world').
Wow. this is some War-n-Peace novel .. time for some hard action, cock slappin code.
Lets bring it!
namespace MyProject.Tests.Repositories.SqlServer
{
// ReSharper disable InconsistentNaming
[TestClass]
public class UserRepositoryTests : TestBase
{
[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
// Arrange.
// NOTE: this method is inherited from the TestBase abstract class.
// Eg. protected IUserRepository =
// new MyProject.Respositories.SqlServer
// .UserRespository(connectionString);
InitializeSqlServerTestData();
}
[TestMethod]
public void GetFirst20UsersSuccess()
{
// Act.
var users = _users.GetUsers()
.Take(20)
.ToList();
// Assert.
Assert.IsNotNull(users);
Assert.IsTrue(users.Count() > 0);
}
}
}
Ok, lets run through this puppy.
First up, this is using Microsoft Unit Testing - built into VS2010 Beta2 or with the Team Foundation edition of VS2008 (or whatever that version is ... i just install the copy our work has purchased).
Second, whenever the class is first initialized (be it one test or many), it creates the context. In my case, my Sql Server UserRepository which will use a LinqToSql context. (Yours will be an EF context). This is the Arrange part of TDD.
Third, i call the method -> this is the Act part of TDD.
Last, I check if i got back what i expected -> this is the Assert part of TDD.
What about updating the DB?
Just follow the same pattern except you might want to wrap your calling code in a transaction and the roll it back. Otherwise u might get 100's of rows of data which could possibly be the same. Downside to this? Any identity fields will not have all nice and pretty numbering sequence (becuase the rollback will 'use' that number). Doesn't make sence? don't worry. that's an advanced tip i thought i'd throw in to test you out, but it means diddly squat for this hellishly long post.
so .. er.. yeah. that's what i do. Don't know if the Gods of Programming, on these forums, will flip and throw mud my way but I sorta like it and I'm hoping it might help ya.
HTH.
You should test the real class not a fake one you make for testing. The point of using an interface is that it allows you to mock out the class, so you can use the mock version in tests with other collaborators.
In order to test the class you should be able to pass in a mock database and assert that the calls you expected to be made in to the database actually happen when you call the methods on your Repository class.
Here is a good intro to mocking and testing in C#:
http://refact.blogspot.com/2007/01/mock-objects-and-rhino.html

Categories