I am working with TDD and all is going well. When I get to my actual Repository though I don't know how to test this.
Consider the code below - this is what I know I want to write but how do I tackle this in a test first way without doing integration testing.
public class UserDb : IUserDb
{
public void Add(User user)
{
using (var context = new EfContext())
{
context.Users.Add(user);
context.SaveChanges();
}
}
}
The link below by forsvarir is what I want to put as an answer. How I can do that?
http://romiller.com/2012/02/14/testing-with-a-fake-dbcontext/
The usual answer to these kinds of questions is:
Isolate the hard to test dependencies (the EF context)
Provide a fake implementation in your tests to verify the correct behaviour of the SUT
This all makes sense when you have interesting logic to test in your system under test. For your specific case, the repository looks like a very thin abstraction between your clean domain and EF-aware logic. Good, keep 'em that way. This also means that it's not really doing much work. I suggest that you don't bother writing isolated unit tests (wrapping EF DbContext seems like extra work that might not pull its weight).
Note that I'm not saying you shouldn't test this code: I often tend to test these thin repositories using a real database, i.e. through integrated tests. For all the code that uses these repositories however, I'd stick to isolated unit testing by providing fake repositories to the system under test. That way I have coverage on my repository code and test that EF is actually talking to my database in the correct way and all other tests that indirectly use these repositories are nice, isolated and lightning-fast.
What are you hoping to achieve by testing the 3rd party tool? You could mock out the context var fakeContext = A.Fake<IDbContext>(); and then assert that an attempt was made to write to the database. A.CallTo(() => fakeContext.SaveChanges()).MustHaveHappened();
The above example uses FakeItEasy mocking library.
Related
For the project I am doing in my internship we have to use a repository pattern. Since the project was already using EF Core and I read that there was already repository and unit of work in the underlying implementation. I figured I would just use the EF Core methods directly without implementing repository classes as I wanted to prevent clutter.
Well now I am in a bit of a problem, I can't seem to find much useful information on unit testing when I implement this way. The requirement is a hard requirement, and I required 100% coverage of CRUD functions within my controllers due to the standards of this firm. I found some of the Microsoft Documentation here, here, and the integration testing using SQLite but I still can't seem to figure out unit testing. I did some googling as well and I can't find resources aside from integration testing.
Is there some way I can unit test using EF Core directly, or am I gonna have to make repositories in order to properly unit test this program?
Since you do not have a separate repository, you do not have to unit test your repository; you cannot unit test what you don’t have.
What you would usually test with EF Core would be actual database access. For that, you can use the in-memory database to temporarily set up your database which you can run full tests against. Of course, this is more an integration test than a minimal unit test.
But you should think about this: When you write unit tests, you have to have an actual idea of what you are testing. Just saying “I need unit tests for component X” does not make real sense. Usually, it would be more like “I need unit tests for methods U, W, Y of component X”. So unless you actually have methods with real behavior that you need to test, attempting to write unit tests for the database context just makes no sense.
You only want to unit test things things that you write yourself. If there’s nothing, e.g. because you are using the direct database context functionalities for CRUD, then there’s nothing to test. The EF Core project is already covering their side with unit tests, and you probably don’t want to start unit testing third party code here.
With EF Core you may use InMemoryDatabase, mock data of your DbContext and test your methods against this data.
Repository adds additional abstraction layer and makes testing a bit more transparent, but it is also possible to inject DbContext with mocked data for your unit tests.
Some code to illustrate an idea
Just don't forget to check is InMemoryDatabase was already passed to the context and do not add another provider in that case.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("ConnectionString");
}
Tip
If you are using ASP.NET Core, then you should not need this code since your database provider is already configured outside of the context (in Startup.cs).
I want to mock the below line of code(by MOQ in C#,MVC) :-
CustomerDto target = CustomerService.GetAllCustomer().FirstOrDefault(n => n.CustomerID == customer.CustomerID);
Where CustomerService.GetAllCustomer() function is the dependency in the controller method.
Where it is using FirstOrDefault() function.And in unit testing i have no clue how to mock it.
Can any one suggest me way for it ?
Mock(stub) your dependency only. In this case it is CustomerService, which should be some interface or abstract class implementation.
Make your GetAllCustomer method return some fake customers.
FirstOrDefault is a .NET Framework method which should not be tested (it is already tested by the framework developers)
IMO, you need to start decoupling your code by moving towards a more layered approach. I am not quite sure what you need to achieve by mocking the FirstOrDefault method. I suggest having three layers and their tests as below -
Data access - uses EF and its DB context and implements a data access interface. You should unit test this without mocking EF's db context. Tests for this layer would be "state" dependent. By that I mean, your tests will work with real data and database for the CRUD operations. You just need to make sure you do not persist the changes to the db after the test run. One can use Spring.Net's testing library to achieve this or simply run your tests under a transaction scope and roll back the transaction after every test run (in the clean up).
Business logic - contains the business logic and works with the data access interface. Use any DI framework like spring.net or ms unity to inject the data access layer. You should unit test this by trying to avoid actual database calls. This is where something like a NMock, Rhinomock or MOQ comes into picture. Set up boundary and exception conditions using mocks and make sure your business logic addresses all the concerns.
MVC Controller - Will delegate the calls to business logic layer and most probably handle stuff like notifications etc needed on the UI. It should be a judgement call if the controller really needs to be unit tested. It could be an overkill more than often. I would rather suggest considering automated UI test cases using something like selenium or Microsoft's coded UI tests.
I'm using NHibernate and the Repository pattern on a fairly large project and am trying to establish my service layer unit testing strategy and am having some problems getting in into my head. It's possible that I'm approaching the unit testing incorrectly, and it's also possible that I'm approaching the Repository pattern incorrectly, but I'm not sure which.
A simplified subset of my scenario looks like this:
public class UserRepository : RepositoryBase, IRepository
{
public UserRepository() {}
public UserRepository( ISession sessionParam ) {
session = sessionParam; // member of repository base
}
public string GetUsernameFromEmail( string emailAddress ) {
return session.QueryOver<Members>().List().Where( u => u.EmailAddress.ToLowerInvariant() == emailAdrress.ToLowerInvariant() ).FirstOrDefault().Username;
}
}
My unit testing concept would be that I would fake NHibernate's ISession and pass in one that returned a list of users that would fit the scenario I'm trying to test (for instance, email address is case-insensitive) (I also can't get this to work with FakeItEasy, but that's for another question, should I proceed down this path). Keeping in mind that we should not fake objects that we don't own, I can see the logic of not wanting to fake the ISession, and I've been reading a lot about how one shouldn't test the repository - that that's too far down for unit tests.
But even in this very basic case there's logic in the repository that I would like to unit test. Other repository methods will have potentially even more logic (data validation and the like, for instance). I know I can use SqlLite or something similar to build relatively fast integration tests for the reporitory, but it still seems to me that this logic should be unit tested.
Relying on the repository there is a (WCF) service tier that's being consumed by an Asp.Net MVC4 site.
In the best of all worlds I would build my unit tests in the WCF tier and fake away the IRepository for testing, but I don't see how I can move this logic to the service tier without getting all of the users from the repository and returning them to the service tier, which seems ridiculous.
So my question is: what piece of the overall architecture here do I have fundamentally wrong in my head?
EDIT
In response to #Wiktor-zychla's answer, here's my logic regarding why I wanted to fake ISession. In thinking about this specific test, I want to have my repository use an implementation of ISession which always returns a single user with a mixed-case email address and a specfic username, pass in an all lower-case email address, and have the return value be the username I instructed my fake to use. That way I am testing my logic against a know value - whether or not that's how NHibernate will operate in the real world isn't my concern here - testing the logic in the repository method is. And again, I know this is a trivial and naive example that could be solved in many other ways - it's just standing in for more complicated functionality that I want to be able to test later.
I don't think you should try to fake the ISession. This doesn't make much sense - the NHibernate repository is a concrete implementation of an abstract concept and what you want to test is that whether or not this concrete implementation is ok rather than abstract it even further and test what? A different, fake linq implementation and then pretend that NH follows it?
Your unit tests should involve a real database then, probably set up before the test starts so that you inject a temp ISession to the repository but still the ISession points to a real database.
On the other hand, it is perfectly valid to have yet another implementation of the repository to be injected in your service layer when you test the service which uses the repository.
In an MVC4 C# website, we are using Unit Testing to test our code. What we are currently doing is creating a mock database, then testing each layer:
Test the Database - connecting, initializing, load, etc.
Test the code accessing the database
Test the view layer
I want these three categories to be run in order and only if the previous one passed. Is this the right way to go about it? The old way we were doing it was using a Dependency Injection framework was a weird approach to mock testing. We actually created a mock class for each data accessor, which sucks because we have to re implement the logic of each method, and it didn't really add any value because if we made a mistake with the logic the first time, we'll make it a second.
I want these three categories to be run in order and only if the
previous one passed. Is this the right way to go about it?
No. You should be test everything in isolation and because of that any failing data access code should be completely unrelated to the view. So the view unit tests should fail for a completely different reason and because of that you should always run all tests.
In general, tests should run in isolation, and should not depend on any other tests. It seems to me that the view layer still depends on the data access code, but that you only abstracted the layer below. In that case, from the view's perspective, you are mocking an indirect dependency, which makes your unit tests more complex than strictly needed.
The old way we were doing it was using a Dependency Injection
framework was a weird approach to mock testing
I'm not sure if I get this, but it seems as if you were using the DI container inside your unit tests. This is a absolute no-no. Don't clutter your tests with any DI framework. And there's no need to. Just design your classes around the dependency injection principle (expose all dependencies as constructor arguments) and in your test you just manually new up the class under test with fake dependencies -or- when this leads to repetitive code, create a factory method in your test class that creates a new instance of the class under test.
We actually created a mock class for each data accessor, which sucks
I'm not sure, but it sounds as if there's something wrong with your design here. You would normally have a IRepository<T> interface for which you would have multiple implementations, such as a UserRepository : IRepository<User>, and OrderRepository : IRepository<Order>. In your test suite, you will have one generic FakeRespository<T> or InMemoryRepository<T> and you're done. No need to mock many classes here.
Here are two great books you should definitely read:
The Art of Unit Testing
Dependency Injection in .NET
Those books will change your life. And since you'll be reading anyway, do read this book as well (not related to your question, but code be a life changer as well).
I've got NHibernate-based (constructor ISessionFactory injection) generic repository implementation which is stored inside DAL. It implements contract which is stored in `Domain Layer'.
Should I test real repository behavior using SQl CE or should I refactor my application to support agnostic-like (like in Tim Maccharty's book http://www.wrox.com/WileyCDA/WroxTitle/productCd-0470147563,descCd-authorInfo.html) Unit of Work and then give my fake implementation of IUnitOfWorkRepository?
Is it a valid approach to run tests on a local database exposing real repository implementation?
Thanks!
The issue is what your are testing and why. That will answer the question.
If:
I want to test a third party tool
That is, are you testing if NHibernate is working (not a kind of test
I do). Then do whatever it requires, so refactoring not required. Loose yourself.
I want to test how my code interacts with a thrid party tool
Then you are talking about what I like to call a interaction test. Refactoring is required as your more interested in how your using NHiberate than if it works.
I want to test my code
The abstract NHibernate entirely. Do whatever is necessary ... wrapper? Your now back into unit testing.
I want to test my application from a user point of view
I think this is above the scope your talking. But you can use this scope talking about components. So ... hmmm ... worthwhile but not easy. Not a unit test, so you want to instantiate the component/app and run the whole thing as its 'user' does. I call these 'UATs' and usually implement as 'Coded UATs'.
A unit test is testing a unit in isolation. So, no, it's not even a unit test if you're going to the database.
Abstract away and test your repositories with mocked up interfaces.
I think to test the repositories you need to use the actual scenario. Otherwise you don't have any other place to test the database access. Mocking the repositories is not a good practice. Because you don't have any logic which is need to test in the repositories. I think you need to write integration tests which is calling actual repositories to have any benefit from it.