Thursday, January 31, 2013

Mvc4 unit(?) testing of views with BDD & SpecFlow

I wanted to unit test my mvc. I had no idea what that could mean. Not my pocos or models, my Mvc. After googling what are the primary targets taken by unit testers? Controllers, almost never Views. The level of complexity behind getting a test framework given v as our view to do v.ExecuteResult() seems over the top immense. The spec flow: Feature: Register a new User In order to register a new User As member of the site So that they can log in to the site and use its features Scenario: Browse Register page When the user goes to the register user screen Then the register user view should be displayed And the view should have a username input field The MsTest class:
using System;
using System.Web.Mvc;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using MvcContrib.TestHelper;

using MvcSpecFlow.Controllers;
using MvcSpecFlow.Views.Account;

using RazorGenerator.Testing;

using TechTalk.SpecFlow;

//http://www.codeproject.com/Articles/82891/BDD-using-SpecFlow-on-ASP-NET-MVC-Application
//http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html
//http://blog.davidebbo.com/2011/06/unit-test-your-mvc-views-using-razor.html

namespace MvcSpecFlow.Tests
{
  [Binding]
  public class RegisterUserSteps
  {
    ActionResult result;

    AccountController controller;

    [When(@"the user goes to the register user screen")]
    public void WhenTheUserGoesToTheRegisterUserScreen()
    {
      controller = new AccountController();
      result = controller.Register();

    }

    [Then(@"the register user view should be displayed")]
    public void ThenTheRegisterUserViewShouldBeDisplayed()
    {
      Assert.IsInstanceOfType(result, typeof(ViewResult));

      var vResult = (ViewResult)result;
      Assert.AreEqual(string.Empty, vResult.ViewName);

      vResult.AssertViewRendered().ForView(string.Empty); //should follow convention not pass a special view name
      
    }

    [Then(@"the view should have a username input field")]
    public void ThenTheViewShouldHaveAUsernameInputField()
    {
      var view = new Register();
      var doc = view.RenderAsHtml();
      var username = doc.GetElementbyId("UserName");
      Assert.IsNotNull(username);
    
    }
  }
}
The requirements:
  1. Use RazorGenerator to precompile your views
  2. The view you are testing has the RazorGenerator set as the Custom Tool
  3. The view you are testing does not have the following razor: @Html.AntiForgeryToken()
  4. Your testing project has RazorGenerator.Testing installed.

No comments:

Post a Comment