Skip to content

Scanning for Test implementation classes using StructureMap with xunit

Thu Feb 18 2010

I have an xunit test project that is using hand-rolled stubs as concrete implementations of interfaces. StructureMap is the DI container I'm using. I was looking at the names of my stubs, and they followed the convention of TestXYZ as the concrete implementation of IXYZ.

To use StructureMap from xunit tests, I created a base class for any fact class that wanted to use ObjectFactory. In the base class ctor, I call the bootstrapper's ConfigureStructureMap method.

At first I just had a bunch of

csharp
x.ForRequestedType<IXYZ>().TheDefaultIsConcreteType<TestXYZ>();

because I had only a handful of stubs and I didn't quite grasp how to scan like the default scanner, only adding "Test" to the beginning of the class name.

Then I found the secret sauce over here, via a method called FindPluginType.

Here is my bootstrapper code for my xunit test project:

csharp
public class TestScanner : ITypeScanner{
  public void Process(Type type, PluginGraph graph) {
    if(type.Name.StartsWith("Test")){
      var pluginType = FindPluginType(type);
      if(pluginType == null)
        return;

      graph.AddType(pluginType, type);
    }				
  }

  static Type FindPluginType(Type concreteType) {
    var interfaceName = "I" + concreteType.Name.Replace("Test", "");
    return concreteType.GetInterfaces().Where(t => string.Equals(t.Name, interfaceName, StringComparison.Ordinal)).FirstOrDefault();
  }
}

public static class Bootstrapper {
  public static void ConfigureStructureMap() {
    ObjectFactory.Initialize(x =>
      {
        x.Scan(s =>
          {
            s.TheCallingAssembly();
            s.WithDefaultConventions();
            s.With<TestScanner>();
          });
        });
      }
}

What results is essentially the DefaultConventionScanner, only it's looking for TestXYZ as the concrete implementation of IXYZ.

Killer.

💾 May the source be with you. v3.2.1118