title: Unit testing with EF Code First DataContext
body: <p>This is more a solution / work around than an actual question. I'm posting it here since I couldn't find this solution on stack overflow or indeed after a lot of Googling.</p>
  
  <p><strong>The Problem:</strong></p>
  
  <p>I have an MVC 3 webapp using EF 4 code first that I want to write unit tests for. I'm also using NCrunch to run the unit tests on the fly as I code, so I'd like to avoid backing onto an actual database here.</p>
  
  <p><strong>Other Solutions:</strong></p>
  
  <p><em>IDataContext</em></p>
  
  <p>I've found this the most accepted way to create an in memory datacontext. It effectively involves writing an interface IMyDataContext for your MyDataContext and then using the interface in all your controllers. An example of doing this is <a href="http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/" rel="nofollow noreferrer">here</a>. </p>
  
  <p>This is the route I went with initially and I even went as far as writing a T4 template to extract IMyDataContext from MyDataContext since I don't like having to maintain duplicate dependent code.</p>
  
  <p>However I quickly discovered that some Linq statements fail in production when using IMyDataContext instead of MyDataContext. Specifically queries like this throw a NotSupportedException</p>
  
  <pre><code>var siteList = from iSite in MyDataContext.Sites
                 let iMaxPageImpression = (from iPage in MyDataContext.Pages where iSite.SiteId == iPage.SiteId select iPage.AvgMonthlyImpressions).Max()
                 select new { Site = iSite, MaxImpressions = iMaxPageImpression };
  </code></pre>
  
  <p><strong>My Solution</strong></p>
  
  <p>This was actually quite simple. I simply created a MyInMemoryDataContext subclass to MyDataContext and overrode all the IDbSet&lt;..> properties as below:</p>
  
  <pre><code>public class InMemoryDataContext : MyDataContext, IObjectContextAdapter
  {
      /// &lt;summary&gt;Whether SaveChanges() was called on the DataContext&lt;/summary&gt;
      public bool SaveChangesWasCalled { get; private set; }
  
      public InMemoryDataContext()
      {
          InitializeDataContextProperties();
          SaveChangesWasCalled = false;
      }
  
      /// &lt;summary&gt;
      /// Initialize all MyDataContext properties with appropriate container types
      /// &lt;/summary&gt;
      private void InitializeDataContextProperties()
      {
          Type myType = GetType().BaseType; // We have to do this since private Property.Set methods are not accessible through GetType()
  
          // ** Initialize all IDbSet&lt;T&gt; properties with CollectionDbSet&lt;T&gt; instances
          var DbSets = myType.GetProperties().Where(x =&gt; x.PropertyType.IsGenericType &amp;&amp; x.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet&lt;&gt;)).ToList();
          foreach (var iDbSetProperty in DbSets)
          {
              var concreteCollectionType = typeof(CollectionDbSet&lt;&gt;).MakeGenericType(iDbSetProperty.PropertyType.GetGenericArguments());
              var collectionInstance = Activator.CreateInstance(concreteCollectionType);
              iDbSetProperty.SetValue(this, collectionInstance,null);
          }
      }
  
      ObjectContext IObjectContextAdapter.ObjectContext 
      {
          get { return null; }
      }
  
      public override int SaveChanges()
      {
          SaveChangesWasCalled = true;
          return -1;
      }
  }
  </code></pre>
  
  <p>In this case my CollectionDbSet&lt;> is a slightly modified version of FakeDbSet&lt;> <a href="http://romiller.com/2012/02/14/testing-with-a-fake-dbcontext/" rel="nofollow noreferrer">here</a> (which simply implements IDbSet with an underlying ObservableCollection and ObservableCollection.AsQueryable()).</p>
  
  <p>This solution works nicely with all my unit tests and specifically with NCrunch running these tests on the fly.</p>
  
  <p><strong>Full Integration Tests</strong></p>
  
  <p>These Unit tests test all the business logic but one major downside is that none of your LINQ statements are guaranteed to work with your actual MyDataContext. This is because testing against an in memory data context means you're replacing the Linq-To-Entity provider but a Linq-To-Objects provider (as pointed out very well in the answer to <a href="https://stackoverflow.com/questions/6766478/unit-testing-dbcontext">this</a> SO question).</p>
  
  <p>To fix this I use Ninject within my unit tests and setup InMemoryDataContext to bind instead of MyDataContext within my unit tests. You can then use Ninject to bind to an actual MyDataContext when running the integration tests (via a setting in the app.config).</p>
  
  <pre><code>if(Global.RunIntegrationTest)
      DependencyInjector.Bind&lt;MyDataContext&gt;().To&lt;MyDataContext&gt;().InSingletonScope();
  else
      DependencyInjector.Bind&lt;MyDataContext&gt;().To&lt;InMemoryDataContext&gt;().InSingletonScope();
  </code></pre>
  
  <p>Let me know if you have any feedback on this however, there are always improvements to be made.</p>