title: Unit Testing ASP.NET MVC5 App
body: <p>I'm extending the ApplicationUser class by adding a new property (as shown in the tutorial
   <a href="http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on" rel="noreferrer">Create an ASP.NET MVC 5 App with Facebook and Google OAuth2 and OpenID Sign-on (C#)</a>)</p>
  
  <pre><code>public class ApplicationUser : IdentityUser
  {
      public DateTime BirthDate { get; set; }
  }
  </code></pre>
  
  <p>Now I want to create a Unit Test to verify that my AccountController is correctly saving the BirthDate.</p>
  
  <p>I've created an in-memory user store named TestUserStore </p>
  
  <pre><code>[TestMethod]
  public void Register()
  {
      // Arrange
      var userManager = new UserManager&lt;ApplicationUser&gt;(new TestUserStore&lt;ApplicationUser&gt;());
      var controller = new AccountController(userManager);
  
      // This will setup a fake HttpContext using Moq
      controller.SetFakeControllerContext();
  
      // Act
      var result =
          controller.Register(new RegisterViewModel
          {
              BirthDate = TestBirthDate,
              UserName = TestUser,
              Password = TestUserPassword,
              ConfirmPassword = TestUserPassword
          }).Result;
  
      // Assert
      Assert.IsNotNull(result);
  
      var addedUser = userManager.FindByName(TestUser);
      Assert.IsNotNull(addedUser);
      Assert.AreEqual(TestBirthDate, addedUser.BirthDate);
  }
  </code></pre>
  
  <p>The controller.Register method is boilerplate code generated by MVC5 but for reference purposes I'm including it here.</p>
  
  <pre><code>// POST: /Account/Register
  [HttpPost]
  [AllowAnonymous]
  [ValidateAntiForgeryToken]
  public async Task&lt;ActionResult&gt; Register(RegisterViewModel model)
  {
      if (ModelState.IsValid)
      {
          var user = new ApplicationUser() { UserName = model.UserName, BirthDate = model.BirthDate };
          var result = await UserManager.CreateAsync(user, model.Password);
          if (result.Succeeded)
          {
              await SignInAsync(user, isPersistent: false);
              return RedirectToAction("Index", "Home");
          }
          else
          {
              AddErrors(result);
          }
      }
  
      // If we got this far, something failed, redisplay form
      return View(model);
  }
  </code></pre>
  
  <p>When I call Register, it calls SignInAsync which is where the trouble will occur.</p>
  
  <pre><code>private async Task SignInAsync(ApplicationUser user, bool isPersistent)
  {
      AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
      var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
      AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
  }
  </code></pre>
  
  <p>At the lowest layer, the boilerplate code includes this tidbit</p>
  
  <pre><code>private IAuthenticationManager AuthenticationManager
  {
      get
      {
          return HttpContext.GetOwinContext().Authentication;
      }
  }
  </code></pre>
  
  <p>This is where the root of the problm occurs.  This call to GetOwinContext is an extension method which I cannot mock and I cannot replace with a stub (unless of course I change the boilerplate code).</p>
  
  <p>When I run this test I get an exception</p>
  
  <pre><code>Test method MVCLabMigration.Tests.Controllers.AccountControllerTest.Register threw exception: 
  System.AggregateException: One or more errors occurred. ---&gt; System.NullReferenceException: Object reference not set to an instance of an object.
  at System.Web.HttpContextBaseExtensions.GetOwinEnvironment(HttpContextBase context)
  at System.Web.HttpContextBaseExtensions.GetOwinContext(HttpContextBase context)
  at MVCLabMigration.Controllers.AccountController.get_AuthenticationManager() in AccountController.cs: line 330
  at MVCLabMigration.Controllers.AccountController.&lt;SignInAsync&gt;d__40.MoveNext() in AccountController.cs: line 336
  </code></pre>
  
  <p>In prior releases the ASP.NET MVC team worked very hard to make the code testable.  It seems on the surface that now testing an AccountController is not going to be easy.  I have some choices.</p>
  
  <p>I can</p>
  
  <ol>
  <li><p>Modify the boiler plate code so that it doesn't call an extension method and deal with this problem at that level</p></li>
  <li><p>Setup the OWin pipeline for testing purposes</p></li>
  <li><p>Avoid writing testing code that requires the AuthN / AuthZ infrastructure (not a reasonable option)</p></li>
  </ol>
  
  <p>I'm not sure which road is better.  Either one could solve this.  My question boils down to which is the best strategy.</p>
  
  <p>Note: Yes, I know that I don't need to test code that I didn't write.  The UserManager infrastructure provided MVC5 is such a piece of infrastructure BUT if I want to write tests that verify my modifications to ApplicationUser or code that verifies behavior that depends upon user roles then I must test using UserManager.</p>