Using SpecsFor.Mvc with Windows Authentication

Specifying your own ApplicationHost.config file for SpecsFor.Mvc to use is the secret to getting Windows Authentication to work. I’m going to assume you’ve already got your web project configured to use Windows Authentication. If not, that’s a can of worms for a different post (or perhaps Stack Overflow?) This post will focus just on configuring the spec project. First, let’s create our host file!

Add a new config file to your spec project called ApplicationHost.config. Modify the properties for this file so that it’s copied to the output directory.

307

Now drop in the standard XML for an IIS Express application config file. If you don’t know what that is (I sure didn’t!), you can use this file from the sample project.

There are two changes you’ll need to make. First, find the element, and change the name of the only site in the file to match the name of the project you’re writing specs against. SpecsFor will overwrite this site definition at runtime.

Next, jump to the end of the file, and add a location block (or change the path on the existing one if you’re using the config file from the sample), like so:

<location path="YOUR_PROJECT_NAME_HERE">
  <system.webServer>
    <security>
      <authentication>
        <windowsAuthentication enabled="true" />
        <anonymousAuthentication enabled="false" />
      </authentication>
    </security>
  </system.webServer>
</location>

Again, be sure you set the path attribute to match the name of the project you are writing specs against!

Now you’re ready to configure SpecsFor.Mvc! Create a setup fixture in the root of your spec project, like so:

[SetUpFixture]
public class SpecConfig
{
    private SpecsForIntegrationHost _host;

    [SetUp]
    public void Setup()
    {
        var config = new SpecsForMvcConfig();
        config.UseIISExpress()
            .ApplicationHostConfigurationFile(@"applicationhost.config")
            .With(Project.Named("WindowsAuthSampleApp"));

        config.UseBrowser(BrowserDriver.InternetExplorer);

        _host = new SpecsForIntegrationHost(config);            
        _host.Start();
    }

    [TearDown]
    public void TearDown()
    {
        _host.Shutdown();
    }
}

Now you can write a spec! In my sample, I had the view output the name of the current user, which should match the current Windows Identity at runtime.

public class HomeControllerSpecs
{
    public class when_viewing_the_home_page : SpecsFor<MvcWebApp>
    {
        protected override void When()
        {
            SUT.NavigateTo<HomeController>(c => c.Index());
        }

        [Test]
        public void then_it_has_the_name_of_the_logged_in_user()
        {
            SUT.FindDisplayFor<HomePageViewModel>()
                .DisplayFor(x => x.UserName).Text.ShouldEqual(WindowsIdentity.GetCurrent().Name);
        }
    }
}

The full source for this sample is available in the samples project on Github.