Notes on Unit Testing in C# with ASP.NET MVC using NUnit, Moq and Selenium
2014-11-06 14:38
Some quick notes on unit testing and testing ASP.NET MVC projects.
Tools
The environment and tools used:
- Microsoft Windows 7
- Microsoft Visual Studio Professional 2013 (could work with Visual Studio Express 2013
- The C# programming language
- NUnit version 2.6.3
- Moq version 4.x
- Selenium IDE version 2.8.0
- Mozilla Firefox version 33.0.2
Add Unit Testing to a Project
- Install the NUnit extension in Visual Studio
- Add test project (use the Class Library template) to solution
- Write test case using NUnit and Moq
Example TestCase with NUnit
A minimal test case is shown here. Setup
and TearDown
methods are only included to show where to create and destroy objects that is of use in more then one test method.
using NUnit.Framework;
using System.Web.Mvc;
using WebApplicationNUnitAndSelenium.Controllers;
namespace NUnitTestDemo
{
[TestFixture]
class Demo
{
[SetUp]
public void Setup() {}
[TearDown]
public void TearDown(){}
[Test]
public void IndexTest()
{
var controller = new HomeController();
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result);
Assert.IsInstanceOf(typeof(HomeController.SomeViewModel), result.Model);
Assert.AreEqual("Some message", result.ViewData["Message"]);
}
}
}
Start Using Selenium
- Install Selenium IDE extension in Firefox
- Record test case
Use Selenium with NUnit in Visual Studio:
- Use NuGet to add "Selenium Webdriver" to the test project
- Use NuGet to add "Selenium Webdriver Support Classes" to the test project
Setup Selenium with InternetExplorer and Chrome (optional)
- Download IE Webdriver from the Selenium download page (choose the appropriate 32 or 64 bit version) and unzip.
- Righ-click on the project name and click "Add existing item..."
- Browse to the folder containing IEDriverServer.exe and choose that file to add to the project
- Under the project tree right-click on the file and click Properties
- Set the value of the field "Copy to Output Directory" to "Copy if newer"
Repeat the same process with the Webdriver for Chrome.
Example TestCase using Selenium
The following example shows a NUnit test case that runs all three browsers. The driver attribute is reset with the appropriate driver for each run. Remove the references to OpenQA.Selenium.Chrome
and OpenQA.Selenium.IE
if you skipped to install the webdrivers for them.
The driver could also be created in the test SetUp
method and then call Quit()
in the TearDown
method. This is suitable for running multiple test case using the same driver.
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Support.UI;
using System;
namespace NUnitTestDemo
{
[TestFixture]
public class SeleniumTests
{
IWebDriver driver;
[Test]
public void FxGoogleSearch()
{
driver = new FirefoxDriver();
GoogleSearch();
driver.Quit();
}
[Test]
public void IeGoogleSearch()
{
driver = new InternetExplorerDriver();
GoogleSearch();
driver.Quit();
}
[Test]
public void ChromeGoogleSearch()
{
driver = new ChromeDriver();
GoogleSearch();
driver.Quit();
}
public void GoogleSearch()
{
//Navigate to the site
driver.Navigate().GoToUrl("http://www.google.com");
// Find the text input element by its name
IWebElement query = driver.FindElement(By.Name("q"));
// Enter something to search for
query.SendKeys("Selenium");
// Now submit the form
query.Submit();
// Google's search is rendered dynamically with JavaScript.
// Wait for the page to load, timeout after 5 seconds
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
wait.Until((d) => { return d.Title.StartsWith("Selenium"); });
//Check that the Title is what we are expecting
Assert.IsTrue(driver.Title.StartsWith("Selenium - "));
}
}
}
Make Use of Moq
Moq is used to create mockups to make unit testing easier. Mockups are phony objects pretending to be of a certain type. This is used to compartmentalize the unit test.
Take a look at Moq Quickstart to get an idea of how to use this.
Comments
It is quite easy to create unit tests and to use Selenium. It get's trickier to test more complicated components and/or when you need a lot of mockups to make a component testable.
Testing ASP.NET MVC controllers can get very complicated and involve a lot of mockups. Since tests are closly coupled with the code this should be visible in the project layout. Put data access layer test code in the data access layer, web frontend testing code with the web frontend and so on.
It is also good practice in general to setup and teardown the database as part of tests. This makes it easy to automate your tests for continous integration (CI) while also making it easy for new developers to setup the database in their development environment.
Among additional tools to improve testing and development the following could be mentioned:
- QUnit - a JavaScript Unit Testing Framework
- Vagrant - for creating reproducible development environments
The direction of ASP.NET vNext and Entity Framework (see EF7 - New Platforms, New Data Stores) will contribute a lot to the testability and overall usability of the ASP.NET framework.
Resources
- NUnit version 2.6.3
- Moq version 4.x
- Selenium IDE version 2.8.0
- Unit Testing and Test Automation in VS2012 Part 1
- Unit Testing and Test Automation in VS2012 Part 2
- SocialGoal by Marlabs
- OWIN - Open Web Interface for .NET
- An Overview of Project Katana
- ASP.NET Web API integration testing with in-memory hosting
- Project Silk: Chapter 13: Unit Testing Web Applications
- Developing, Architecting and Testing Web Applications with MVC 5, Web API 2, KnockoutJS, Ninject and NUnit