So I am working on getting 100% code coverage for my tests on fFastMapper (My tool to do high-speed, precompiled mapping between 2 objects). The following method is a single line and was being called in my tests. However, Visual Studio 2013's code coverage tool was reporting that there was a block of code left untested. I couldn't see any way this was possible.
public static TReturn Map<TLeft, TReturn>(this fFastMapperFluent<TLeft, TReturn> fluent, TLeft source) where TReturn : new() { return fFastMapperInternal<TLeft, TReturn>.mapperFunc(source, new TReturn()); }
So I dragged out ILSpy thinking that I would have to slog through the IL (intermediate language that C# compiles to) to figure this one out. I do this sometimes and find it educational but I don't do it enough that it comes natural. As it turns out, I didn't need to go that far because the decompiled C# version of the method gave me my answer.
public static TReturn Map<TLeft, TReturn>(this fFastMapperFluent<TLeft, TReturn> fluent, TLeft source) where TReturn : new()
{
return fFastMapperInternal<TLeft, TReturn>.mapperFunc(source, (default(TReturn) == null) ? Activator.CreateInstance<TReturn>() : default(TReturn));
}
Because my generic method supported being called by both value types and reference types, the compiler turns "new TReturn()" into 2 calls. If the type is a value type, the code just returns the default of that type, but if it is a value type, it calls Activate.CreateInstance<TReturn> to create the new instance.
One solution to get code coverage for this code would have been to write another test that called this code with a value type. However, this code wasn't actually intended to be used with value types so I fixed this by adding the generic constraint of "class".
public static TReturn Map<TLeft, TReturn>(this fFastMapperFluent<TLeft, TReturn> fluent, TLeft source)
where TReturn : class,new()
{
return fFastMapperInternal<TLeft, TReturn>.mapperFunc(source, new TReturn());
}
Now the code compiles as intended and the code coverage tool shows that I have coverage of that method.