Sunday, February 24, 2013

Using Microsoft Fakes to Unit Test Entity Framework

If you have used Entity Framework, then I am sure you have read in various blogs that using the Repository pattern is the best way to test it.

Though I hardly have the expertise to challenge that notion, I take that statement with caution. The pattern itself is great for usages where you want to shield your data access from your middle tier, my personal opinion is that the most value of a repository pattern is achieved when you want to access disparate sources but provide a consistent experience of interacting with entities.

So the idea of introducing a pattern for the sake of testability seemed a bit strange. For one, I couldn’t fathom why the application should carry the weight of an additional pattern when it is going to be used only for testing. So I went about exploring alternate options of testing EF without using the repository pattern. Its no secret that I am an admirer of Fakes (Wrote about its ancestor Pex and Moles here), so I decided to see if Fakes will stand up to the challenge of unit testing EF.

The structure of my solution itself is fairly trivial. I have a service project with an edmx in it and one GetValue method that returns an entity from my table using EF. A unit test project completes the solution.

image

My service method

   1: public class FakesService : IFakesService
   2:     {
   3:         public MyEntity GetValue(int value)
   4:         {
   5:             using (MyDbContext entities = new MyDbContext())
   6:             {
   7:                 return entities.MyEntities.Find(value);
   8:             }
   9:         }
  10:     }

This is the method I want to test. To shim my EF entities, I created a Fakes Assembly for the service dll in my test project..


The method that we are interested in shimming is the MyEntitiesGet; done with the code below



   1: ShimMyDbContext.AllInstances.MyEntitiesGet = (shimContext) =>
   2: {
   3:     return shimContext.MyEntities;
   4: };

 

But there is an issue with the above snippet. I am detouring the Entities Get to execute my code, but not mocking anything. Because the shimContext has a reference to MyDbContext, the code executed will still be the EF code, pointing to the database. To truly mock this, I will have to create a fake DbContext.

 


   1: public class FakesContext : DbContext
   2:    {
   3:        public DbSet<MyEntity> MyEntities { get; set; }
   4:        public FakesContext()
   5:        {
   6:            
   7:        }
   8:    }

To have this constructor invoked when MyDbContext class is initialized, it has to be shimmed



   1: MyDbContext.Constructor = (paramDbContext) => GenerateConstructor();
   2: private DbContext GenerateConstructor()
   3:         {
   4:             return new FakesContext();
   5:         }

So, that’s all!! Or so it would seem. Just when I was ready to celebrate my little victory of mocking EF, something hit when I debugged the test method.


image


The line that was causing this error was


return entities.MyEntity.Find(value);


Digging a bit more, I found that the using statement was the culprit and the error occurred in Dispose method of the DbContext object in EF. At first I was left scratching my head. But then I realised that since we are mocking the constructor, it is trying to dispose the original MyDbContext class and it isn’t able to. After trying various alternatives, I came to the conclusion that the only way to get around this is to shim the Dispose method of the EF DbContext. To do this, I had to generate a Fakes Assembly for the EntityFramework dll (I am using EF 5). I wasn’t sure how well Fakes was going to handle this but to my surprise, it went smoothly enough and I ended up with the method below.



   1: ShimDbContext.AllInstances.Dispose = (context) => DummyDispose();
   2: private void DummyDispose()
   3: { 
   4: }

The only thing left to do now, is to return my own list of entities instead of ones from the database. We go back to the EntitiesGet shim to do that. The code for that now looks something like the below.



   1: MyDbContext.AllInstances.MyEntitiesGet = (shimContext) =>
   2: {
   3:     FakesContext dummyContext = new FakesContext();
   4:     Database.SetInitializer<FakesContext>(null);
   5:     Entity entity1 = new Entity();
   6:     entity1.Id = 1;
   7:     entity1.Name = "First created from test";
   8:     dummyContext.MyEntities.Add(entity1);
   9:     Entity entity2 = new Entity();
  10:     entity2.Id = 2;
  11:     entity2.Name = "Second created from test";
  12:     dummyContext.MyEntities.Add(entity2);
  13:     return dummyContext.MyEntities;
  14: };

Nothing out of ordinary except for the SetInitializer statement. That is to turn off tracking by EF. There is a post by Scot Hanselman (I think) on it, so I wont go into it too much.


So there you go! A successfully mocked unit test on EF. I have to admit that I haven’t tried mocking other EF methods and there could be challenges there, but with this little exercise, I am fairly confident that those challenges can be overcome.  Happy Coding!!

Friday, December 7, 2012

My experiments with Windows Azure Mobile Services- Part II

The first post on this topic was written in October here. Though I wanted to follow it up quickly with Part II, I got distracted, but here I am with the second part of Azure Mobile Services.

One of the things that wasn’t detailed in the first post was the Ratings class. So I will start from there. The ratings class is simply an instance of the ratings table in the database. It hence inherits the AzureMobileTable class that we saw in the previous post.

The table has the columns listed below

image

The scenario that we will deal with in this post, is to calculate the Average ratings for any given movie. This can be  done in two ways

  • Get all the movies to the service and calculate the average in the service. The downside of this is that if I have a lot of ratings for a movie I have to fetch all the records which is inefficient.
  • The second option is to calculate the Average in Azure Mobile Services and return the records. The question though is, how to do this with Azure Mobile Services.

Azure Mobile Services has support for scripting. Every table has a tab called script and when you click on it, you will see that you can write your script for 4 operations; Insert, Update, Delete and Read. This is what we will use for calculating averages. But there is a catch. Each operation just supports one implementation of the script. The read, for example by default executes read all, which we have already used. So you cannot write another read script to do Averages.

One way to get around this limitation is to create another Azure Mobile Service table called Averages and script the read operation of this table to calculate averages for the ratings table. Some code snippet is in order. So here goes

   1: function read(query, user, request) {
   2:     mssql.query("SELECT AVG(Value) as Average from Ratings WHERE MovieID = ?", [query.id], {
   3:         success:function(results) {
   4:             request.respond(200, results[0]);    
   5:         }
   6:     });
   7:     //console.log(query);
   8:     //console.log(query.getComponents());
   9: }

The script calculates the average for a given movie id and returns the status of 200 along with the results. The commented code just show you how to use logging.


Now, what is left to do is to call this from our service described in Part I. There is a method in the Ratings class that calls this script.



   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Web;
   5:  
   6: namespace TMDBHelperService.AzureMobileServices
   7: {
   8:     public class Ratings: AzureMobileTable
   9:     {
  10:         public Ratings():base("ratings")
  11:         {
  12:             
  13:         }
  14:  
  15:         public AzureMobileQuery getAverage(int movieId)
  16:         {
  17:             return new AzureMobileQuery("tables/averages/" + movieId.ToString());
  18:         }
  19:     }
  20: }

Note the getAverage method queries against the Averages table and not the ratings table. The only other thing left to do is to call this method from our broker.



   1: public string getAverageRatings(int movieId)
   2:         {
   3:             var _ratingsTable = new Ratings();
   4:             AzureMobileQuery _query = _ratingsTable.getAverage(movieId);
   5:             if (_query!=null)
   6:             {
   7:                 return _helperClass.Execute(_query);    
   8:             }
   9:             return String.Empty;
  10:         }


This solution works very well if you just have one or two operations. But it quickly becomes unmanageable if you have write a bunch of custom operations on a table.


The better way of doing this is to use custom parameters. You can pass custom parameters by appending them as query strings to the table uri. Something like below


tables/ratings?ops=avg&movieid=<movieid>


Then change the ratings read query to do different operations based on these parameters.



   1: function read(query, user, request) {
   2:     if(request.parameters.ops == "avg")
   3:     {
   4:         console.log(request.parameters.ops);
   5:         console.log(request.parameters.movieid);
   6:         mssql.query("SELECT AVG(Value) as Average from Ratings WHERE MovieID = ?", [request.parameters.movieid], {
   7:             success:function(results) {
   8:                 request.respond(200, results[0]);    
   9:             }
  10:         });
  11:     }
  12:     else
  13:     {
  14:         request.execute();
  15:     }
  16: }

This is a bit more elegant way of “overloading” the read operation without the overhead of additional tables.


I find myself using Azure Mobile Services more and more. I love the simplicity of it for small applications and the speed with which I can get it up and running. They are not perfect but if you are on the fence, I highly encourage you to try them.

Wednesday, October 10, 2012

My experiments with Windows Azure Mobile Services – Part I

 

In August, Microsoft released a new Azure service called Windows Azure Mobile Services. These services, make developing windows store apps easier. If you haven’t started taking a look at it, you can start here.  If you are thinking about using them in your app, you have to be aware of the fact that the javascript client and the server side client versions have some differences.

While most of the fundamentals are the same, I believe the C# version of the Mobile Services Client is a bit more comprehensive than the Javascript version. This being the first version, I am hoping they are going to have the same features across both the clients.

This post deals with using the client in javascript apps. I am not going to go into the details of how to get it working. There is a lot of literature out there that covers this. In short, you download the extension for javascript, get your app key from the portal and use the client library to make calls to the service.

This works very well. With a couple of lines of code, you get your data to the app. But, I was wary of leaving the app key in the client machine. I also want all my business rules in the service not in the client app.

So I was looking to access the Mobile Services from a service.Also, my app already talks to a service that I host on azure, so I wanted all logic to be on the service not on the client. Unfortunately, you can’t use the client library in a WCF Service project.  So I decided to figure out how to call the Mobile Services from a service.

At the backend, the Mobile Services client library just calls a REST API. You can see this by stepping through the code in MobileServices.js. The code that actually makes the call is

   1: Platform.webRequest(options, handler);

Once I figured that out, I decided to write code in my service that does the same.


Let me give you some context  about what my app does. The app allows users to rate movies. It talks to an external webservice to get the list of movies and stores the ratings in Azure Mobile Web Services table. My Azure Mobile Service table structure is shown below


image


The MovieId stores the movie id from the external service and the Value column stores the ratings of the movie. This is the table I am going to query from my service.


image


I created the classes above to do this. A brief description of the classes before we delve into the code within each of them


AzureMobileTable – This loosely represents an Azure Mobile Services Table. I say loosely because,  the methods here are not present in Azure Mobile Services. These will be translated into REST URIs  as you will shortly see.


AzureMovieBroker – This acts as the broker between the WCF service and Azure Mobile Services. This will implement the methods that are needed by the app.


AzureMobileHelper – This is the helper class that runs the methods on Azure Mobile Services. i.e. Makes the REST call. The helper class always executes a query on a table, so it needs a handle to both these objects.


AzureMobileQuery – This class makes up the queries. Queries like where, order by and so on.


Ratings – This is the implementation of the ratings table we saw earlier. This class extends the functionality of the Azure table by providing custom operations. Average is an example. All tables might not need an Average operation. For the app, the ratings table returns the average rating for a movie.


Now that we have looked at the classes, let us see how the code works. First the MobileHelper



   1: public class AzureMobileHelper
   2:     {
   3:         string _baseurl;
   4:         string _appKey;
   5:         string _installationId;
   6:  
   7:         public AzureMobileHelper(string url, string appKey, string installationId)
   8:         {
   9:             _baseurl = url;
  10:             _appKey = appKey;
  11:             _installationId = installationId;
  12:         }
  13:  
  14:         public AzureMobileTable getTable(string tableName)
  15:         {
  16:             return new AzureMobileTable(tableName);
  17:         }
  18:  
  19:         public string Execute(AzureMobileQuery query)
  20:         {
  21:             string fullUri = _baseurl + query.Uri;
  22:             HttpWebRequest _azureRequest = WebRequest.Create(fullUri) as HttpWebRequest;
  23:             _azureRequest.Headers.Add("X-ZUMO-APPLICATION", _appKey);
  24:             
  25:             _azureRequest.Headers.Add("X-ZUMO-INSTALLATION-ID", _installationId);
  26:             using (HttpWebResponse restResponse = _azureRequest.GetResponse() as HttpWebResponse)
  27:             {
  28:                 Encoding enc = System.Text.Encoding.GetEncoding(1252);
  29:                 StreamReader _jsonStream = new StreamReader(restResponse.GetResponseStream(),enc);
  30:                 return _jsonStream.ReadToEnd();
  31:             }
  32:         }
  33:  
  34:     }

The MobileHelper constructor takes three arguments. The url, the appKey and the installation id. The appKey and the Installation Id are used by Azure Mobile Services to authenticate a request. This is based on a setting in the management portal (You can also choose to authenticate using LIVE Id). You will get the appKey and the url from the management portal. I got the installation id from MobileServices.js (this will be in the request header). At the moment, I don’t know of another way to get it.


The getTable method returns a handle to the AzureMobileTable object. We will take a look at the MobileTable constructor momentarily.


The execute method is the method that does the job. It creates a web request, adds the necessary headers and reads the response returning it as a string. Any response received from Mobile Services is in the JSON format. Pretty simple.



   1: public class AzureMobileTable    
   2: {
   3:     string _tableName = string.Empty;
   4:     private  string tableUrl { 
   5:         get{
   6:             return "tables/" + _tableName;
   7:         }
   8:     }
   9:  
  10:     public AzureMobileTable(string tableName)
  11:     {
  12:         _tableName = tableName;
  13:     }
  14:  
  15:     
  16:     
  17:     public AzureMobileQuery Where(string whereExpression)
  18:     {
  19:         Expression convertedExpression = Expression.Constant(whereExpression);
  20:         if (convertedExpression is MethodCallExpression)
  21:         {
  22:             return null;
  23:             throw new Exception("Invalid Expression");
  24:         }
  25:         return new AzureMobileQuery(tableUrl + "?$filter=" + whereExpression);
  26:     }
  27: }

The AzureMobileTable class in a way, is the glue that sort of holds everything together. It does this very simply, by building the URIs. The constructor takes in the table name and builds the URI for a table by prefixing  tables/.


At the moment, the class only has one filter operation which is Where. It first validates if this is a valid LINQ Expression and if it is, constructs the appropriate URI. I will be adding more operations, but you get the idea. The last class we will see in this post is the AzureMobileQuery



   1: public class AzureMobileQuery
   2: {
   3:     public string Uri { 
   4:         get{
   5:             return _uri;
   6:         }
   7:     }
   8:     private string _uri;
   9:     public AzureMobileQuery(string uri)
  10:     {
  11:         _uri = uri;
  12:     }
  13: }

The class is pretty much self explanatory. The last piece of the jigsaw is the Broker class that initiates the call.



   1: public string getRatingsbyId(int movieId)
   2:         {
   3:             AzureMobileHelper _helperClass = new AzureMobileHelper("<url>", "<appKey>", "<installationid>");
   4:             AzureMobileTable _moviesCollection = _helperClass.getTable("ratings");
   5:             AzureMobileQuery _query = _moviesCollection.Where("MovieId eq '" + movieId + "'");
   6:             if (_query != null)
   7:             {
   8:                 return _helperClass.Execute(_query);
   9:             }
  10:             return String.Empty;
  11:         }

The method instantiates the helper class with app specific url, app key and installation id. As explained before, it then gets a handle to the table that the query needs to be executed on and the actual query that gets executed. The query in this case just filters all entries for a given movie id.


I have consciously not touched on the ratings class because it solves another problem area that I will deal with in the next post. The above code is just an illustration of how services can call Azure Mobile Services.


The fact that Azure Mobile Services is based on REST gives the developers great flexibility on how to access it and what to do with it. I am not sure when the Mobile Services team plan to release a client library for services or if they even plan to, but if you need to access the services from a service, this has hopefully given you a starting point. Happy Coding!!!