Mocking services for integration tests

In one of my recent projects where we used Castle Windsor as IoC framework we wanted make integration tests. This involved mocking some external services to ensure predictability in the test.
As we wanted to our WCF REST endpoints we could not register mocked instances in our test case as we would normally do. Instead the test would include a) informing server that this is a integration test request (on a per request basis) and b) on the fly resolving of services so we could swap the real service with a mocked service.

To identify all my mocked integration services I introduced a common interface. To make this a little more concrete I will use the example where I have an interface IAppleSupplierService which is implemented by AppleSupplierService. During integration tests I want to use the AppleSupplierIntegrationTestService instead. The AppleSupplierIntegrationTestService must implement both IAppleSupplierService and IIntegrationTestImplementation.

public interface IIntegrationTestImplementation
{
   ...
}

public interface AppleSupplierIntegrationTestService : IAppleSupplierService, IIntegrationTestImplementation
{
   ...

To support the on the fly resolving I created a custom implementation of the IHandlerSelector. The SelectHandler method finds and returns the handler which should be used to resolve the given type. If the method returns null Castle Windsor will ignore the result from this IHandlerSelector.
In this method we return null if we are not running an integration test. If we are running an integration test we search the available handlers for an implementation which implements both the given service interface and the IIntegrationTestImplementation interface.

public class IntegrationTestHandlerSelector : IHandlerSelector
{
   public bool HasOpinionAbout(string key, Type service)
   {
      return true;
   }

   public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
   {
      if (!IntegrationTestHelper.IntegrationTestRequest()) return null;

      var handler = handlers.SingleOrDefault(
                    h => h.ComponentModel.Implementation.GetInterfaces().Contains(typeof(IIntegrationTestImplementation)) &&
                     h.ComponentModel.Implementation.GetInterfaces().Contains(service));
            return handler;
   }
}

The two different implementations of the service interface must of course be registered with the Castle Windsor container. This must be done in such a manner that the real implementation is used as default and the integration test implementation is only used as a fallback option.

public class IntegrationRegistration : IWindsorInstaller
{
   public void Install(IWindsorContainer container, IConfigurationStore store)
   {
      container.Register(Component.For<IAppleSupplierService>().ImplementedBy<AppleSupplierService>().LifestylePerWebRequest());
      container.Register(Component.For<IAppleSupplierService>().ImplementedBy<AppleSupplierIntegrationTestService>().LifestylePerWebRequest().IsFallback());
   }
}

There you have it. On the fly resolving of services allowing you to swap to a different implementation while performing integration test.

Auto-mocking dependencies for unit test

In one of my finished projects I worked on a solution where we used dependency injection. In this set up we used Castle Windsor as inversion of control framework, and Moq as mocking framework.

Castle Windsor made it easy to include new dependencies in our services. However introducing a new dependency would make a dozen unit tests break because the new dependency was not supplied in our test setup. This gave a great deal of unnecessary maintenance.

This example will describe how to introduce auto-mocking using castle windsor as IoC framework and Moq as mocking frameworking. Auto-mocking will give us a default mocked implementations of all the services we do not specifically register with Castle Windsor. The example is based on Auto-mocking Container by Mark Seemann.

We create a custom ISubDependencyResolver which will allow us to resolve a mocked instance of any interface. In the Resolve method we check if the kernel can resolve an implementation of the given interface and we return this as default. If this is not possible a mocked instance of the interface is returned.

public class AutoMoqResolver : ISubDependencyResolver
{
   private readonly IKernel _kernel;</code>

   public AutoMoqResolver(IKernel kernel)
   {
      _kernel = kernel;
   }

   public bool CanResolve(
      CreationContext context,
      ISubDependencyResolver contextHandlerResolver,
      ComponentModel model,
      DependencyModel dependency)
   {
      return dependency.TargetType.IsInterface;
   }

   public object Resolve(
      CreationContext context,
      ISubDependencyResolver contextHandlerResolver,
      ComponentModel model,
      DependencyModel dependency)
   {
      if (_kernel.HasComponent(dependency.TargetType))
         return _kernel.Resolve(dependency.TargetType);
      var mockType = typeof(Mock&lt;&gt;).MakeGenericType(dependency.TargetType);
      return ((Mock)_kernel.Resolve(mockType)).Object;
   }
}

The AutoMockInstaller class implements the IWindsorInstaller interface. The AutoMoqResolver is added as a sub resolver and we register for mocked instances.

public class AutoMockInstaller : IWindsorInstaller
{
    public void Install(
       IWindsorContainer container,
       IConfigurationStore store)
    {
       container.Kernel.Resolver.AddSubResolver(
          new AutoMoqResolver(container.Kernel));
       container.Register(Component.For(typeof(Mock<>)));
    }
}

The auto-mocker is now finished and ready for use in unit tests. Below we have a basic example of how you can create the Windsor container, use the AutoMockInstaller, and register two specific services. If you resolve the IFruitStoreService the ChiquitaService will be injected as IBananaSupplierService and (Mock<IAppleSupplierService).Object will be injected as IAppleSupplierService.

public class FruitStoreService : IFruitStoreService {
   public FruitStoreService (IBananaSupplierService bananaSupplier, IAppleSupplierService appleSupplierService)
   {
      ...
   }
}

[TestFixtureSetUp]
public void RegisterServices(IWindsorContainer container)
{
   _container = new WindsorContainer().Install(new AutoMockInstaller());
   _container.Register(Component.For<IFruitstoreService>().ImplementedBy<FruitstoreService>());
   _container.Register(Component.For<IBananaSupplierService>().ImplementedBy<ChiquitaService>());
}

Specific mocked methods can be setup like so

   var appleSupplierService= container.Resolve<Mock<IAppleSupplierService >>();
   appleSupplierService.Setup(x => x.GetAppleVarieties()).Returns(new List<string>(){"Granny Smith","Pink Lady"});

 

Prevent RemoteAPI access to user info list

We developed an application open to the public on a sharepoint 2010 platform. Part of the developed functionality depends on the RemoteAPI which allows querying of lists via the listdata.svc service. The RemoteAPI is actuallyquite nice as it exposes list data via OData.

You can restrict access to the individual lists using the regular sharepoint permission functionality. One list you should be aware of is the user info list. Enabling the remote API will make this list accessable. On a danish sp2010 the list will have the endpoint /_vti_bin/ListData.svc/ListeMedBrugeroplysninger and will effectively allow a single malicious user to browse for all data in the user info list.

As this is not a regular list you cannot use standard sharepoint permission functionality. We tried to make around by disabling RemoteAPI in general and only allowing it on certain lists. This didn’t work.

We found that altering the following property on user info list prevented access via the RemoteAPI without breaking other functionality:
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splist.showuser.aspx

So here is how you prevent the user info list from being queryable via the RemoteAPI:

$w = get-spweb [RootWeb]
$ul = $w.SiteUserInfoList
$ul.ShowUser = $false
$ul.Update()

Lets Merge Two SPUsers… Famous last words

Why did we try this
A client has a sharepoint 2010 claims based solution. Several person entries have been converted from their old system. Duplicate person entries exist and due to other circumstances in the solution, new duplicates may be created. A custom claim provider allows the customer to find and populate people pickers with persons. Whenever a person is added to a new site collection the person is ensured and a new SPUser is created. Therefore we end up with multiple SPUsers which in fact represent the same user. So when the customer merges the two person database entries we want to merge the two SPUsers.

Background info
It is a demand that all out current people picker fields (UserField) will function correctly after we have merged our users so let us take a look on how they work. If you look at an item containing a UserField you will see that the value is of the form “’ID;#Person name”.

fieldinfo

The UserField is in fact a lookup field and the ID references the ItemId in the given list. If you follow the trail you will see that we are referencing the UserInfoList. A list containing the SPUsers for our site collection.
(You can read more about the UserInfoList here )

The Task
We want to merge two SPUsers. The best bet of doing this is the SPMove-User method which according to the documentation “Migrates a user account in SharePoint 2010 Products.”. The hope is that Move-SPUser –Identity PersonEntryOneClaim –NewAlias PersonEntryTwoClaim. Will create a single SPUser with the claim of PersonEntryTwoClaim and having all the UserFields update their reference two the combined SPUser.
The Move-SPUser method will iterate through appropriate sitecollections in the farm and use the old STSADM migrateuser command to migrate the user.
Afterwards PersonTwo is no longer visible on the UserInfo list and PersonOne now has the login value PersonEntryTwoClaim but retains all other original values.
userinfo
If you look in the content database you will see that deleted the tp_Deleted field is set to the ID of the user in the UserInfo list. So the only connection between the deleted and “combined” SPUser is the identical Login. This is however not static and if we performed another merge aftwerwards where PersonOne is merged into PersonThree the link between PersonOne and PersonTwo would be lost.
The conclusion of all this is that since there is no link between PersonOne and PersonTwo, the value of all our UserFields must be updated by the migrateuser command if this merging is going to work.

If we take a look on a UserField which referenced PersonTwo we will see that the value is still ’10;#PersonEntryTwoName’. It therefore still references PersonTwo in the UserInfo list where he does not exist. So the migrate user command did not update the UserFields.

Conclusion: Don’t use SPMove-User to merge two users. It simply doesn’t work.

Returning 401 in a ASP.Net solution with Windows Forms Authentication

In one of the solutions I have worked on we are hosting REST (Not really Restful but whatever) services on Sharepoint 2010 server using WCF. These services are used for serving data to the client side browser using AJAX. One of the pitfalls we discovered was that while you were not logged in the services would not give an acceptable answer to the browser. This is because we via Sharepoint use windows forms authentication. In normal scenarios the server will respond with a 302 HTTP status code and redirect the browser to the login page. This might make sense for a browsing user but it makes little sense for a web service client.

We tried setting the status code to 401 explicitly on the outgoing response but the FormsAuthenticationModule substitutes the 401 with a 302 to redirect the browser to the login page.
I found the solution to this problem in this blog post

Basically the options are:

  1. disable forms authentication module
  2. Do it yourself
  3. Download a package where someone fixed it for you

Doing it yourself by writing the module was quite straightforward so we chose that approach. What we will do is to hook into response pipeline. Detect an ajax request using http headers and detect a redirect by the 401 status code before this is altered by the FormsAuthenticationModule. If we detect such a request/response we will save the value in the HttpContext and later in the pipeline change the value back to 401.

public class SuppressFormsAuthenticationRedirectModule: IHttpModule
{
/* Identifier for our key */
private static readonly object SuppressAuthenticationKey = new Object();

/* Setting the key */
public static void SuppressAuthenticationRedirect(HttpContext context)
{
context.Items[SuppressAuthenticationKey] = true;
}
/* Setting the key */
public static void SuppressAuthenticationRedirect(HttpContextBase context)
{
context.Items[SuppressAuthenticationKey] = true;
}

/* Init hooking into the pipeline */
public void Init(HttpApplication context)
{
context.PostReleaseRequestState += OnPostReleaseRequestState;
context.EndRequest += OnEndRequest;
}

/* Detect 401 for ajax requests and set key */
private void OnPostReleaseRequestState(object source, EventArgs args)
{
var context = (HttpApplication)source;
var response = context.Response;
var request = context.Request;

if (response.StatusCode == 401 && request.Headers["X-Requested-With"] == "XMLHttpRequest")
{
SuppressAuthenticationRedirect(context.Context);
}
}

/* Change status code to original value */
private void OnEndRequest(object source, EventArgs args)
{
var context = (HttpApplication)source;
var response = context.Response;

if (context.Context.Items.Contains(SuppressAuthenticationKey))
{
response.TrySkipIisCustomErrors = true;
response.ClearContent();
response.StatusCode = 401;
response.RedirectLocation = null;
}
}

Now all you need to do is register you http module and send set the 401 value.
My frontend guy was exceptionally happy when he saw the first 401 response.
I can recommend original post the by Phil Haack