Code first architecture with ASP.NET MVC3 and Entity Framework

architecture asp.net-mvc code-first entity-framework unit-testing

Question

Zzz-3-Zzz led me to rethink architectural concepts like layers, repositories, dependency injection, and similar things.

This is how my architecture now looks:
I simply created POCO classes and context since I am utilizing EF code initially. Db and model are created as a result.
Class levels for business layers are higher (Providers). I create new instances of my DbContext in each of these providers, and I use a different provider for each domain, such as MemberProvider, RoleProvider, TaskProvider, etc.
I then create these providers in my controllers, collect the data, and transmit it to the views.

Repository was a part of my original design, but I removed it after hearing that it merely increases complexity and was unnecessary. I wanted to do that—work with EF straight from controllers—but I had to build tests, and using a real database made things more difficult. I had to somehow create phony or mock data. Therefore, I created an interface for each provider and created fictitious providers with lists of hardcoded data. And with that, I returned to a situation in which I am unsure how to continue effectively.

These things begin to overcomplicate too rapidly; there are too many techniques and "patterns," which results in excessive noise and pointless code.

Is there a STEP-BY-STEP design that is TESTABLE and SIMPLE for building ASP.NET MVC3 applications using Entity Framework?

1
53
5/23/2017 12:24:09 PM

Accepted Answer

Writing integration or end-to-end tests is a need if you wish to utilize TDD (or any other testing methodology with good test coverage) and EF together. Any strategy that includes mocking, whether in the context of a repository or elsewhere, provides tests that can only test the higher layer logic (which makes use of those mocks), not your application.

Simple illustration

Definition of a generic repository

public interface IGenericRepository<TEntity> 
{
    IQueryable<TEntity> GetQuery();
    ...
}

Let's now create some business procedures:

public IEnumerable<MyEntity> DoSomethingImportant()
{
    var data = MyEntityRepo.GetQuery().Select((e, i) => e);
    ...
}

Now, if you use Linq-To-Objects to mimic the repository, you will have a successful test. However, if you use Linq-To-Entities to execute the application, you will get an error since select overload with indexes is not supported in L2E.

This was a straightforward example, but the same may be said for utilizing methods in queries and other frequent errors. Additionally, this has an impact on commonly available repository methods like Add, Update, and Delete. You cannot test your implementation until you create a fake that accurately replicates the behavior of EF context and referential integrity.

Problems with lazy loading are another aspect of the tale that are difficult to identify using unit tests against mocks.

This calls for the addition of integration or end-to-end tests that will run against actual databases while using actual EF context and L2E. By the way, utilizing TDD properly requires employing end-to-end tests. You may use WatiN and SpecFlow for BDD when building end-to-end tests for ASP.NET MVC, however this will add a lot of effort and ensure that your application is well tested. I suggest reading more about TDD at these pages (the only disadvantage is that examples are in Java).

If you don't use a generic repository and you put your queries in a class that won't expose them, integration tests make sense.IQueryable but provides info directly.

Example:

public interface IMyEntityRepository
{
    MyEntity GetById(int id);
    MyEntity GetByName(string name); 
}

Because queries are concealed in this class and not accessible to higher levels, you can now simply build integration tests to test the implementation of this repository. However, this kind of repository is seen as an outdated implementation when utilized with stored procedures. With this solution, you will either lose a lot of ORM functionality or have to put in a lot of extra effort, such as adding definition of a pattern to enable query definition in the higher layer.

End-to-end testing may be largely replaced with integration tests at the controller level in ASP.NET MVC.

Based on a remark, edit:

I disagree that you should do end-to-end, integration, and unit tests. I believe that creating tested apps requires far more work. The complexity of the application, the anticipated future of the application, your talents and the skills of other team members will all affect how many and what kinds of tests are required.

Even though it's not a good idea, we've all created small, straightforward projects without any tests, and in the end, they worked. However, once a project crosses a certain threshold, adding new features and maintaining it become very challenging because you can never be sure if they won't break something that already works. This is known as regression. An effective collection of automated tests is the strongest defense against regression.

  • You may test a method using unit tests. Ideally, these tests would cover each possible method execution route. These tests should be quick and simple to create; the most difficult element may be establishing dependencies (mocks, faktes, stubs).
  • Integration tests allow you to evaluate functionality that often spans many processes and different levels (application, database). They aren't necessary for every situation; rather, knowing when to use them depends more on experience.
  • End-to-end tests serve as a kind of use case, user narrative, or feature validation. They must satisfy the whole of the criteria.

It is not necessary to test a feature more than once; for example, you do not need to create an integration test for the same code if you are aware that the feature has already through end-to-end testing. Additionally, you don't need to create unit tests for a function if you are aware that it has a single execution route that is covered by integration testing. With the TDD methodology, where you begin with a large test (end-to-end or integration) and go further to unit tests, this works much better.

Depending on your development strategy, you don't have to incorporate several test types right away; instead, you may do so as your application becomes more complicated. The TDD/BDD approach is an exception, where you should begin using unit and end-to-end tests before writing a single line of additional code.

Therefore, you are posing an incorrect query. What is simpler is not the question. What will ultimately assist you and what level of complexity suits your application are the questions. You should wrap the EF code into some other classes that can be mocked if you want to have easily unit tested business logic and applications. To make sure the EF code works, however, you must also create other kinds of tests.

I can't tell you which strategy will work best for your situation, project, team, etc. But I can provide an example from a previous project:

Together with two colleagues, I worked on the project for roughly 5–6 months. The project was built using incremental and iterative development methods and was based on ASP.NET MVC 2 + jQuery + EFv4. It had a great deal of intricate business logic and intricate database queries. To verify mapping, we began with generic repositories and strong code coverage using unit tests and integration tests (simple tests for inserting, deleting, updating and selecting entity). After a few months, we discovered that our strategy is ineffective. We had a lot of regression issues, more than 1.200 unit tests, and a code coverage of just approximately 60%. Any modification to the EF model has the potential to cause unforeseen issues in components that have not been modified in a number of weeks. We discovered that our application logic lacks integration tests or end-to-end testing. A parallel team working on a different project came to the same conclusion, and employing integration tests was suggested for future projects.

93
4/10/2011 3:00:39 PM

Popular Answer

Do repository patterns provide additional complexity? I don't believe so in your circumstance. Your code becomes more manageable and TDD is made simpler. To get more separation and clearer code, try to adopt a generic repository approach.

Visit http://msdn.microsoft.com/en-us/ff714955.aspx if you want to learn more about TDD and design patterns in Entity Framework.

You seem to be seeking for a method to fake test Entity Framework, however. Utilizing a virtual seed mechanism to produce data during database creation is one way. Seed portion may be found at http://blogs.msdn.com/b/adonet/archive/2010/09/02/ef-feature-ctp4-dbcontext-and-databases.aspx.

Some mimicking frameworks are also available for usage. The best-known ones I am aware of are:

Visit https://stackoverflow.com/questions/37359/what-c-mocking-framework-to-use to get a more comprehensive list of.NET mimicking frameworks.

Utilizing an in-memory database provider like SQLite is an alternative strategy. Visit Exists an Entity Framework in-memory provider? to learn more.

Finally, the following list of useful websites on unit testing Entity Framework includes those that mention Entity Framework 4.0. But you'll understand.)

http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/678b5871-bec5-4640-a024-71bd4d5c77ff

http://mosesofegypt.net/post/Introducing-Entity-Framework-Unit-Testing-with-TypeMock-Isolator.aspx

How do I go about simulating my database layer in a unit test?



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow