One of the selling points of ASP.NET MVC 2.0 was the ability to unit test your action methods. Even though Microsoft made MVC flexible by making it easier to unit test than web forms, it isn't always easy to implement without writing a lot of code to implement fakes for common services you use or without abstracting the interface altogether. For instance, the HttpContextBase class is an abstract base class that you can use to abstract using the context, but you'd have to create a class that inherits from this and implement the respective methods. As another example, you've probably seen controllers that implement an interface like IProductsRepository, and use an injection tool like Castle Windsor or Microsoft Unity to inject a reference into the controller's constructor.
Enter mocking libraries, making this process easier to do. TypeMock makes this very easy to do, and you don't even need to write a fake or worry about dynamic injection (unless you want to, because after all, DI is pretty cool and flexible). Let's look at an example controller action method below:
public class ProductsController : Controller
{
public ActionResult Get(int key)
{
var repos = new ProductsRepository();
var product = repos.GetByKey(key);
if (product == null)
throw new Exception("The product couldn't be found");
return View(product);
}
}
Here we have a reference to the ProductsRepository; it's a repository class serving up data from a LINQ to SQL backend. TypeMock makes it easy to construct some tests to ensure that the action method works as expected, that it throws the error when the product is null, and that it returns the view when the product exists.
First Test - Forcing an Exception
The first test verifies that when no product returns from the database, an exception is thrown.
[Test]
public void Get_ReturningNullProductFromDBThrowsException()
{
//Arrange
var repos = Isolate.Fake.Instance<ProductsRepository>();
Isolate.WhenCalled(() => repos.GetByKey(123)).WillReturn(null);
Isolate.Swap.NextInstance<ProductsRepository>().With(repos);
var controller = Isolate.Fake.Instance<ProductsController>(Members.CallOriginal);
//Act
try
{
var result = controller.Get(123);
Assert.Fail();
}
catch (Exception ex)
{
Assert.AreEqual("The product couldn't be found", ex.Message);
}
Isolate.CleanUp();
}
TypeMock's Isolate.Fake mechanism creates a fake for the product repository, and overtakes the GetByKey method to force a null returned value. This works great to force the result, but we need the SwapNextInstance call to ensure that the next new ProductsRepository statement returns the fake.
Second Test - Finding Product OK
The second test checks that a valid product gets served up to the view. The way to check that is to invoke the action result of the action method, check that the result is a view result, and checks its ViewData.Model property, as illustrated below.
[Test]
public void Get_ReturningProductFromDBPassesToModel()
{
//Arrange
var product = new DA.Product { ProductID = 123 };
var repos = Isolate.Fake.Instance<ProductsRepository>();
Isolate.WhenCalled(() => repos.GetByKey(123)).WillReturn(product);
Isolate.Swap.NextInstance<ProductsRepository>().With(repos);
var controller = Isolate.Fake.Instance<ProductsController>(Members.CallOriginal);
//Act
var result = controller.Get(123);
//Assert
Assert.IsInstanceOf<ViewResult>(result);
Assert.AreEqual(product, ((ViewResult)result).ViewData.Model);
Isolate.CleanUp();
}
Instead of returning a null product, this test returns a dummy Product instance through a fake ProductsRepository.
Third Test - Exception Bubbling
The third check tests that when an exception occurs within the product repository, that the exception bubbles up from the repository.
[Test]
public void Get_ErrorFromProviderBubblesUp()
{
//Arrange
var repos = Isolate.Fake.Instance<ProductsRepository>();
Isolate.WhenCalled(() => repos.GetByKey(123)).WillThrow(new Exception("Test"));
Isolate.Swap.NextInstance<ProductsRepository>().With(repos);
var controller = Isolate.Fake.Instance<ProductsController>(Members.CallOriginal);
//Act
try
{
var result = controller.Get(123);
Assert.Fail();
}
catch (Exception ex)
{
//Assert
Assert.AreEqual("Test", ex.Message);
}
Isolate.CleanUp();
}
Instead of returning a product, the WillThrow method simulates throwing an exception. When calling the Get method, should throw an exception, which it does pass the test.
Normal
0
false
false
false
EN-US
X-NONE
X-NONE
I recently installed TFS 2010 and began to setup my
projects, so I decided to create this blog post. I’m not going to cover the installation
aspect of TFS; rather, I’m going to assume that you successfully installed the
base software; this blog doesn’t discuss the use of the proxy or the build
service either, just the TFS product and Sharepoint Services 3.0. If you have a SharePoint server, this is
supported; however, there are a few more setup procedures available online. To begin, let’s open up Visual Studio 2010,
open the project, and open up the Team Explorer tool window on the right. Click the far right icon of the toolbar,
Connect to Team Project.

Normal
0
false
false
false
EN-US
X-NONE
X-NONE
If you have made a connection previously, that entry appears
in the “Team Project Collections” list; if you don’t have your target TFS
specified, click the Servers button.

Normal
0
false
false
false
EN-US
X-NONE
X-NONE
On the Add/Remove Server screen, click add, and specify the
server to add. Either type in the server
name directly, or enter in the full URL.
If you type in the server name, specify the path and port in the
respective textboxes.

Normal
0
false
false
false
EN-US
X-NONE
X-NONE
Clicking OK will add the entry to the list. Click close on the Add/Remove TFS
screen. In the previous screen (Connect
to Team Project), select the newly added server and click Connect. You are connected to the server.
A TFS admin may have to setup a collection for your project;
by default, the DefaultCollection is the only collection projects can be added
to; having a separate collection means that project can be backed up and
restored independently of other projects.
These collections setup on the server are what you see in the team
explorer. Right click one of the collections, and select New Team Project:

Normal
0
false
false
false
EN-US
X-NONE
X-NONE
In the opening screen, enter the name and
description of the project.

Normal
0
false
false
false
EN-US
X-NONE
X-NONE
Click next when finished.
The next screen asks for the template you would like to use for the
project.

Normal
0
false
false
false
EN-US
X-NONE
X-NONE
Click next to configure the Sharepoint portal site. Team Foundation Server is integrated with
SharePoint and installs SharePoint Services 3.0 if you do not have the full SharePoint
server installation. By default, if
follows a <server>/sites/<collection name>/<project> folder
structure. Click configure to change
some of the SharePoint settings.
Note: if you don’t have permissions, you may not be able to
create the SharePoint site. The
SharePoint site can be created manually and linked to the project after
installation. If you don’t have
permissions, select “Do not configure a SharePoint site at this time”.

Normal
0
false
false
false
EN-US
X-NONE
X-NONE
Next, specify the location for the project, or branch it
from another project.

Normal
0
false
false
false
EN-US
X-NONE
X-NONE
Finally, view the final statistics and ensure that the
project is setup correctly.

Normal
0
false
false
false
EN-US
X-NONE
X-NONE
This communicates with the server and setups the following
project structure within the Team Explorer:

Normal
0
false
false
false
EN-US
X-NONE
X-NONE
Now our team system project is setup. The following items in this list are:
Work Items – A place to add work items, assign them to
members of the team, and so on. Use team
queries to get a predefined query of work items, or create your own queries in
the “My Queries” option.
Documents – A document library location for you to store
documents related to the project.
Reports – Any reports for the project setup in Reporting
Services by the installation.
Builds – Any builds defined by the build service for the
project.
Source Control – Visit this feature to add your
projects to the source control database for the first time.