Note that there are some explanatory texts on larger screens.

plurals
  1. POEntity Framework 4.1 Integration Unit Tests
    primarykey
    data
    text
    <p>First, a few caveats:</p> <p>We are building a small/medium sized system that is anticipated to have a lifespan of 2-5 years (relatively short). The system is being developed with Entity Framework 4.1, Code First, MVC3. We are trying to push our team towards unit testing / TDD. It is something that we have not done, but we recognize its value so are taking baby steps in that direction. </p> <p>With all of that in mind, we have decided to build unit tests with Visual Studio 2010's built-in testing framework. We are NOT using the repository pattern or mocks. This is to reduce the complexity and time spent building the unit tests. Each unit test is really more of an integration test - we have a 'test' database that gets initialized each time the tests are run, and each test uses the same controllers that the views use to get as close as we can to real-world behavior of the system.</p> <p>When commenting or answering this question, <em>please do not attack this approach</em>. I am well aware that this is not TDD in its purest form nor is it the ideal pattern for testing units of work. We are doing it this way to get our feet wet with the technology and try to get the most bang for our buck in terms of time spent building the unit tests.</p> <p><strong>The Problem:</strong></p> <p>We are building a lot of unit tests that store an object via a controller, then retrieve the object from the database through the controller to verify that it was stored correctly and that it comes back through our controller the way we would expect. Here is an example:</p> <pre><code>[TestMethod] public void Edit_Post_Saves_OperatingCompany_In_DB_When_OperatingCompany_Is_Valid() { OperatingCompany opco = new OperatingCompany(); opco.Name = "OpCo - Edit Post - Valid - DB Save"; controller = new OperatingCompanyController(); controller.Create(opco); Guid opcoid = opco.Id; controller = new OperatingCompanyController(); opco = (OperatingCompany) ((ViewResult)controller.Edit(opcoid)).Model; opco.Name = "Edit - OpCo - Edit Post - Valid - DB Save"; controller = new OperatingCompanyController(); HelperMethods.AddValidationResultsToModelState(opco, controller); controller.Edit(opco); controller = new OperatingCompanyController(); ViewResult result = controller.Index(); Assert.IsTrue(((IEnumerable&lt;OperatingCompany&gt;)result.Model).Contains(opco)); } </code></pre> <p>The error we are getting is this: </p> <p><strong>Test method WebObjects.Tests.Controllers.OperatingCompanyControllerTest.Edit_Post_Saves_OperatingCompany_In_DB_When_OperatingCompany_Is_Valid threw exception: System.InvalidOperationException: An entity object cannot be referenced by multiple instances of IEntityChangeTracker.</strong></p> <p>I am pretty sure this is occuring because the entity in question isn't being detached from the context of the first controller, and when we reinstantiate it and try to edit the same entity, it thinks another context still has ahold of it. The reason we are reinstantiating the controller is to ensure that the entity is being pulled back from the database and not just being returned from the cache of the DbContext (please correct me if I am wrong here, but I believe that is what would be happening if we didn't reinstantiate).</p> <p>We were able to get this to work by explicitly detaching every object from the context after every call to SaveChanges as well as detaching when we query objects via the context in our controllers, but I don't want to do that just to get our unit tests to work, plus I am sure it would be a significant performance hit. </p> <p><strong>The Question:</strong></p> <p>Is there some better way to perform this type of integration test with our controllers?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload