Brian Mains

Catch me on linked in at: http://linkedin.com/in/brianmains, or follow me on twitter at: @brianmains.

May 2010 - Posts

Unit Testing ASP.NET MVC 2.0 With TypeMock

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.

Posted: Tue, May 25 2010 20:50 by bmains | with no comments
Filed under: , ,
Setting Up a Team Foundation Server 2010 Project

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.