I am trying to create a unit test to verify that my method to load AutoMapper configurations works correctly. My idea to load AutoMapper configurations is to put the configuration calls in classes with the following interface:
public interface IEntityMapConfiguration
{
void ConfigureMapping();
}
To load these dynamically, I have the following loader class
public class EntityMapLoader
{
public static void LoadEntityMappings()
{
// Load all IEntityMapConfiguration classes via reflection
var types = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(x => x.IsSubclassOf(typeof(IEntityMapConfiguration)))
.Select(x => x as IEntityMapConfiguration)
.ToList();
foreach (var config in types)
config.ConfigureMapping();
}
}
To verify this I have created the following unit test
public class UnitTestEntityViewModel
{
public int Id { get; set; }
public int Text2 { get; set; }
}
public class TestProjectionMapping : IEntityMapConfiguration
{
public void ConfigureMapping()
{
Mapper.CreateMap<UnitTestEntity, UnitTestEntityViewModel>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
.ForMember(dest => dest.Text2, opt => opt.MapFrom(src => src.Text));
}
}
[TestClass]
public class AutomapperConfigurationTests
{
[TestMethod]
public void Loader_Loads_All_Configurations_In_Assembly()
{
// Setup
UnitTestEntity entity = new UnitTestEntity { Id = 2, Text = "Test 1234" };
// Act
EntityMapLoader.LoadEntityMappings();
// Verify
UnitTestEntityViewModel result = Mapper.Map<UnitTestEntity, UnitTestEntityViewModel>(entity);
Assert.AreEqual(entity.Id, result.Id, "View model's ID value did not match");
Assert.AreEqual(entity.Text, result.Text2, "View model's text value did not match");
}
}
The problem is that this unit test fails because it’s not picking up my TestProjectionMapping class, and I can’t figure out why. In my LoadEntityMappings() the types list has a count of zero. I have verified that my test assembly is returned from AppDomain.CurrentDomain.GetAssemblies().
I’m sure I am doing something obviously wrong, but I can’t find it. Any ideas?
Edit: I updated my LoadentityMappings() method to be:
public static void LoadEntityMappings()
{
// Load all IEntityMapConfiguration classes via reflection
var types = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(x => x.GetInterfaces().Contains(typeof(IEntityMapConfiguration)))
.Select(x => x as IEntityMapConfiguration)
.ToList();
foreach (var config in types)
config.ConfigureMapping();
}
This is still failing. The statement (without the final select) is returning my TestProjectionMapping class, but the x as IEntityMapconfiguration is failing. In the debugger when I type (IEntityMapConfiguration)types[0] I get the following error:
Cannot cast 'types[0]' (which has an actual type of 'System.RuntimeType') to 'MyJobLeads.DomainModel.EntityMapping.IEntityMapConfiguration'
For reference in the watch list typing types[0] shows:
types[0] {Name = "TestProjectionMapping" FullName = "MyJobLeads.Tests.TestProjectionMapping"} System.Type {System.RuntimeType}
Also, types[0] is IEntityMapConfiguration is false
I’m not sure why I can’t do this cast, any ideas?
You can’t use
Type.IsSubclassOfto see if a type implements an interface. You have to useType.IsAssignableFrom(or you can useis IEntityMapConfigurationorType.GetInterfacesand then see if the resulting sequence containstypeof(IEntityMapConfiguration).Now think about why you can’t use
Type.IsSubclassOfto see if aTypeimplements an interface. Because we don’t say that a class that implements an interface is a subclass of that interface; instead we say that it implements the interface, and we reserve is subclass of for its base class (objectorValueTypeunless one is specified).By the way, this is clearly spelled out in the documentation for
Type.IsSubclassOf: