We run more private classes than public classes, and we have different ticket options based on purchasing power globally. Take advantage of our Retraining Programs and Advocate Programs!

Solution: Testing Web Services with MSTest on Team Foundation Build Services 2010


No items found

Table of Contents

Guess what. About 20 minutes after I fixed the build, Allan broke it again!


Update: 4th March 2010 – After having huge problems getting this working I read Billy Wang’s post which showed me the light.

The problem here is that even though the test passes locally it will not during an Automated Build. When you send your tests to the build server it does not understand that you want to spin up the web site and run tests against that! When you run the test in Visual Studio it spins up the web site anyway, but would you expect your test to pass if you told the website not to spin up? Of course not. So, when you send the code to the build server you need to tell it what to spin up.

First, the best way to get the parameters you need is to right click on the method you want to test and select “Create Unit Test”. This will detect wither you are running in IIS or ASP.NET Development Server or None, and create the relevant tags.


Figure: Right clicking on “SaveDefaultProjectFile” will produce a context menu with “Create Unit tests…” on it.

If you use this option it will AutoDetect most of the Attributes that are required.

/// <summary>
///A test for SSW.SQLDeploy.SilverlightUI.Web.Services.IProfileService.SaveDefaultProjectFile
// TODO: Ensure that the UrlToTest attribute specifies a URL to an ASP.NET page (for example,
// http://.../Default.aspx). This is necessary for the unit test to be executed on the web server,
// whether you are testing a page, web service, or a WCF service.
[AspNetDevelopmentServerHost("D:WorkspacesSSWSSWSqlDeployDEVMainSSW.SQLDeploy.SilverlightUI.Web", "/")]
public void SaveDefaultProjectFileTest()
    IProfileService target = new ProfileService(); // TODO: Initialize to an appropriate value
    string strComputerName = string.Empty; // TODO: Initialize to an appropriate value
    bool expected = false; // TODO: Initialize to an appropriate value
    bool actual;
    actual = target.SaveDefaultProjectFile(strComputerName);
    Assert.AreEqual(expected, actual);
    Assert.Inconclusive("Verify the correctness of this test method.");

Figure: Auto created code that shows the attributes required to run correctly in IIS or in this case ASP.NET Development Server

If you are a purist and don’t like creating unit tests like this then you just need to add the three attributes manually.



  • HostType – This attribute specified what host to use. Its an extensibility point, so you could write your own. Or you could just use “ASP.NET”.
  • UrlToTest – This specifies the start URL. For most tests it does not matter which page you call, as long as it is a valid page otherwise your test may not run on the server, but may pass anyway.
  • AspNetDevelopmentServerHost – This is a nasty one, it is only used if you are using ASP.NET Development Host and is unnecessary if you are using IIS. This sets the host settings and the first value MUST be the physical path to the root of your web application.

OK, so all that was rubbish and I could not get anything working using the MSDN documentation. Google provided very little help until I ran into Billy Wang’s post  and I heard that heavenly music that all developers hear when understanding dawns that what they have been doing up until now is just plain stupid.

I am sure that the above will work when I am doing Web Unit Tests, but there is a much easier way when doing web services.

You need to add the AspNetDevelopmentServer attribute to your code. This will tell MSTest to spin up an ASP.NET Development server to host the service. Specify the path to the web application you want to use.

[AspNetDevelopmentServer("WebApp1", "D:WorkspacesSSWSSWSqlDeployDEVMainSSW.SQLDeploy.SilverlightUI.Web")]
public void ProfileService_Integration_SaveDefaultProjectFile_Returns_True()
    ProfileServiceClient target = new ProfileServiceClient();

    bool isTrue = target.SaveDefaultProjectFile("Mav");

    Assert.AreEqual(true, isTrue);

Figure: This AspNetDevelopmentServer will make sure that the specified web application is launched.

Now we can run the test and have it pass, but if the dynamically assigned ASP.NET Development server port changes what happens to the details in your app.config that was generated when creating a reference to the web service? Well, it would be wrong and the test would fail.

This is where Billy’s helper method comes in. Once you have created an instance of your service call, and it has loaded the config, but before you make any calls to it you need to go in and dynamically set the Endpoint address to the same address as your dynamically hosted Web Application.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;
using System.ServiceModel.Description;
using System.ServiceModel;

namespace SSW.SQLDeploy.Test
    class WcfWebServiceHelper

        public static bool TryUrlRedirection(object client, TestContext context, string identifier)
            bool result = true; 
            try { 
                PropertyInfo property = client.GetType().GetProperty("Endpoint");
                string webServer = context.Properties[string.Format("AspNetDevelopmentServer.{0}", identifier)].ToString(); 
                Uri webServerUri = new Uri(webServer); 
                ServiceEndpoint endpoint = (ServiceEndpoint)property.GetValue(client, null); 
                EndpointAddressBuilder builder = new EndpointAddressBuilder(endpoint.Address); 
                builder.Uri = new Uri(endpoint.Address.Uri.OriginalString.Replace(endpoint.Address.Uri.Authority, webServerUri.Authority)); 
                endpoint.Address = builder.ToEndpointAddress(); 
            catch (Exception e) { 
                context.WriteLine(e.Message); result = false; 
            return result;

Figure: This fixes a problem with the URL in your web.config not being the same as the dynamically hosted ASP.NET Development server port.

We can now add a call to this method after we created the Proxy object and change the Endpoint for the Service to the correct one. This process is wrapped in an assert as if it fails there is no point in continuing.

[AspNetDevelopmentServer("WebApp1", D:WorkspacesSSWSSWSqlDeployDEVMainSSW.SQLDeploy.SilverlightUI.Web")]
public void ProfileService_Integration_SaveDefaultProjectFile_Returns_True()
    ProfileServiceClient target = new ProfileServiceClient();
    Assert.IsTrue(WcfWebServiceHelper.TryUrlRedirection(target, TestContext, "WebApp1"));

    bool isTrue = target.SaveDefaultProjectFile("Mav");

    Assert.AreEqual(true, isTrue);

Figure: Editing the Endpoint from the app.config on the fly to match the dynamically hosted ASP.NET Development Server URL and port is now easy.

As you can imagine AspNetDevelopmentServer poses some problems of you have multiple developers. What are the chances of everyone using the same location to store the source? What about if you are using a build server, how do you tell MSTest where to look for the files?

To the rescue is a property called” “%PathToWebRoot%” which is always right on the build server. It will always point to your build drop folder for your solutions web sites. Which will be “tfs.ssw.com.auBuildDrop[BuildName]Debug_PrecompiledWeb” or whatever your build drop location is. So lets change the code above to add this.

[AspNetDevelopmentServer("WebApp1", "%PathToWebRoot%SSW.SQLDeploy.SilverlightUI.Web")]
public void ProfileService_Integration_SaveDefaultProjectFile_Returns_True()
    ProfileServiceClient target = new ProfileServiceClient();
    Assert.IsTrue(WcfWebServiceHelper.TryUrlRedirection(target, TestContext, "WebApp1"));

    bool isTrue = target.SaveDefaultProjectFile("Mav");

    Assert.AreEqual(true, isTrue);

Figure: Adding %PathToWebRoot% to the AspNetDevelopmentServer path makes it work everywhere.

Now we have another problem… this will ONLY run on the build server and will fail locally as %PathToWebRoot%’s default value is “C:Users[profile]DocumentsVisual Studio 2010Projects”. Well this sucks… How do we get the test to run on any build server and any developer laptop.

Open “Tools | Options | Test Tools | Test Execution” in Visual Studio and you will see a field called “Web application root directory”. This is where you override that default above.

Figure: You can override the default website location for tests.

In my case I would put in “D:WorkspacesSSWSSWSqlDeployDEVMain” and all the developers working with this branch would put in the folder that they have mapped.

Can you see a problem?

What is I create a “$/SSW/SqlDeploy/DEV/34567” branch from Main and I want to run tests in there. Well… I would have to change the value above. This is not ideal, but as you can put your projects anywhere on a computer, it has to be done.


Although this looks convoluted and complicated there are real problems being solved here that mean that you have a test ANYWHERE solution. Any build server, any Developer workstation.








Need Help?


SSW was the first company in the world outside of Microsoft to deploy Visual Studio 2010 Team Foundation Server to production, not once, but twice.

Team Foundation Server

Visual Studi2010 ALM SSW provides expert Visual Studio ALM guidance including installation, configuration and customisation through our four Microsoft Visual Studio ALM MVP’s in three countries; Australia, Beijing and the UK. They have experience deploying to small development shops all the way through to large blue chips.

Professional Scrum Developer Training

Professional Scrum Developer Training SSW has six Professional Scrum Developer Trainers who specialise in training your developers in implementing Scrum with Microsoft’s Visual Studio ALM tools.

Create a conversation around this article

Share on facebook
Share on Facebook
Share on twitter
Share on Twitter
Share on linkedin
Share on Linkdin
Share on pinterest
Share on Pinterest

Want to learn more?

Check out the many training classes that we have.

No items found


We believe that every company deserves high quality software delivered on a regular cadence that meets its customers needs. Our goal is to help you reduce your cycle time, improve your time to market, and minimise any organisational friction in achieving your goals.

naked Agility Limited is a professional company that offers training, coaching, mentoring, and facilitation to help people and teams evolve, integrate, and continuously improve.

We recognise the positive impact that a happy AND motivated workforce, that has purpose, has on client experience. We help change mindsets towards a people-first culture where everyone encourages others to learn and grow. The resulting divergent thinking leads to many different ideas and opportunities for the success of the organisation.