In my last post, I showed how you could use mocking frameworks and dependency injection to create unit tests for methods that query a database using Entity Framework. In this post, I will show how you can use the same techniques to test data access code that will insert, update or delete a record from the database.
For the purposes of demonstrating this, we will continue to use the Exchange Rate example that has been used previously and implement code so that we can insert, update, and delete Exchange Rate records.
Exchange Rate Model
To start with, we will need a model to represent the Exchange Rate.
By creating a separate Business Model to represent the Exchange Rate, we can add additional validations or logic to the business layer without having to worry about changing the underlying Entity Model. In this case, we will have the Id on the business model represented by a nullable integer. Later, we will check whether it is null to determine whether we are inserting or updating a record.
Inserting a New Record
At this point, we are going to use some of the features of the IDbSet and will need to modify our IDatabaseEntities to support our ability to access these features. We’ll modify IDatabaseEntities as follows:
Note that we’ve modified the ExchangeRates property to return an IDbSet rather than an IQueryable and we’ve add the SaveChanges method.
At this point, we can write the unit test for inserting a new record. We will do this by creating a mock of the IDatabaseEntities as well as a mock of the IDbSet. When inserting a record via Entity Framework, a call gets made to Add on the Entity Set and then a call is made to SaveChanges on the Data Context. The following test checks for these conditions using the Verifiable method of the mock. Whenever a Mock Setup is identified as Verifiable, this means that when the call to Verify is made at the end of the test, if the call was not made, this will result in a unit test failure.
The call to Verify at the end of the unit test will validate that the calls to Add occurred on the IDbSet and that the call to SaveChanges occurred on the IDatabaseEntities.
Now, we will implement the method to insert the record:
At this point, we now have a SaveExchangeRate method that will save a new record and a unit test for this functionality.
Updating an Existing Record
Next, we will write a unit test to update an existing record. In Entity Framework, to update a record, you first query for the entity from the Entity Set. After this, if you make a change to the entity and then call SaveChanges, the updates are applied to the database. The difficult part is setting up our IDbSet mock to actually allow a query to be executed against it. To do this, we can create an IQueryable out of a list by calling the AsQueryable() extension method. This would look like the following:
Once we have the Queryable, we need to let the mock for the IDbSet know that we want it to behave as that Queryable. This is done with the following set of code:
Now, we can write our unit test as follows:
Next, to update the SaveExchangeRate method so that it can update an existing record, we’ll add the following else condition:
Deleting a Record
First, we’ll write the unit test. When deleting a record from Entity Framework, the entity must first be retrieved similarly to how an entity is updated. After that, we call the Remove method on the IDbSet to remove it, and then the SaveChanges method on the Data Context. The following unit test verifies this:
Next, the code that implements DeleteExchangeRate follows:
Now we have written data access methods for inserting, updating, and deleting records from the ExchangeRate entity set. We also have unit tests that ensure these methods work as desired. If you would like to see the entire source code for my previous blog post as well as this one, the solution can be found at https://obsblogposts.codeplex.com/ in the EffectiveUnitTests-EntityFramework directory.
- Entity Framework - http://msdn.microsoft.com/en-us/data/ef.aspx
- Moq - http://www.nuget.org/packages/Moq
- Effective Unit Testing – Part 3: Entity Framework - http://ig.obsglobal.com/2014/06/effective-unit-testing-part-3-entity-framework/
- Source Code - https://obsblogposts.codeplex.com/