Fake DbContext of Entity Framework 4.1 to Test

前端 未结 5 1818
再見小時候
再見小時候 2020-11-22 17:19

I\'m using this tutorial to Fake my DbContext and test: http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/

5条回答
  •  难免孤独
    2020-11-22 17:47

    "Unfortunately you are not doing it right because that article is wrong. It pretends that FakeContext will make your code unit testable but it will not"

    I am the creator of the blog post that you refer to. The problem I see here is a misunderstanding of the fundamentals of N-Layered unit testing. My post is not meant to be used directly to test controller logic.

    A unit test should do exactly as the name implies and test 'One Unit'. If I am testing a controller (as you are doing above) I forget all about the data access. I should be removing all of the calls to database context in my mind and replacing them with a black box method call as if those operations were unknown to me. It is the code around those operations that I am interested in testing.

    Example:

    In my MVC application we use the repository pattern. I have a repository, say CustomerRepository : ICustomerRepository, which will perform all of my Customer database operations.

    If I were to test my controllers would I want the tests to test my repository, my database access, and the controller logic itself? of course not! there are many 'units' in this pipeline. What you want to do is create a fake repository which implements ICustomerRepository to allow you to test the controller logic in isolation.

    This to the best of my knowledge cannot be done on the database context alone. (except maybe for using Microsoft Moles, which you can check out if you want). This is simply because all queries are performed outside of the context in your controller class.

    If I wanted to test the CustomerRepository logic how would I do that? The easiest way is to use a fake context. This will allow me to make sure that when I'm trying to get a customer by id, it actually gets the customer by id and so forth. Repository methods are very simple and the "Cannot be translated into a store expression" problem will not usually surface. Though in some minor cases it may (sometimes due to incorrectly written linq queries) in these cases it is important to also perform integration tests that will test your code all the way through to the database. These problems will be found in integration testing. I have used this N-Layered technique for quite a while now and have found no problems with this.

    Integration Tests

    Obviously testing your app against the database itself is a costly exercise and once you get tens of thousands of tests it becomes a nightmare, on the other hand it best mimics how the code will be used in the 'real world'. These tests are important (from the ui to the database) also and they will be performed as part of the integration tests, NOT unit tests.

    Acaz, what you really need in your scenario is a repository which is mockable/fakeable. If you wish to test your controllers as you are doing then your controller should be taking in an object which wraps the database functionality. Then it can return anything you need it to in order to test all aspects of your controller's functionality.

    see http://msdn.microsoft.com/en-us/library/ff714955.aspx

    In order to test the repository itself (debated if needed in all cases) you will want to either fake the context or use something along the lines of the 'Moles' framework.

    LINQ is inherently hard to test. The fact that the query is defined outside of the context using extension methods gives us great flexibility but creates a testing nightmare. Wrap your context in a repository and this problem goes away.

    sorry so long :)

提交回复
热议问题