Comments on: Generics and NMock https://blog.mattwynne.net/2007/10/17/generics-and-nmock/ Matt Wynne taking it one tea at a time Wed, 21 Aug 2019 13:07:17 +0000 hourly 1 https://wordpress.org/?v=6.2 By: Bobby https://blog.mattwynne.net/2007/10/17/generics-and-nmock/comment-page-1/#comment-16 Wed, 17 Oct 2007 17:31:21 +0000 http://blog.mattwynne.net/2007/10/17/generics-and-nmock/#comment-16 s the matcher. Basically it uses reflection (MethodInfo). It caught us out at first as the first time it hits the matcher (when you set the expectation) as the method had not been made concrete (ContainsGenericParameters). It hits the Matcher again when the method gets called and voila the test fails. <pre> public class GenericMethodMatcher : Matcher { private readonly string methodName; private readonly Type expectedType; private string errortext = String.Empty; public GenericMethodMatcher(string methodName, Type expectedType) { this.methodName = methodName; this.expectedType = expectedType; } public override bool Matches(object o) { MethodInfo methodInfo = o as MethodInfo; if (methodInfo.Name == methodName) { //if this is true it means the method has not been called yet so will not have our argument yet. if (methodInfo.ContainsGenericParameters) return true; foreach (Type type in methodInfo.GetGenericArguments()) { if (expectedType == type) return true; } errortext = string.Format("Generic method{0} called with unexpected type parameter. Expected: {1} ", methodName, expectedType); return false; } return false; } public override void DescribeTo(TextWriter writer) { Console.WriteLine(errortext); } } } } </pre> ]]> Here’s how its done:


Expect
   .Once
   .On(StubbedInvoker.fooFacade)
   .Method(new GenericMethodMatcher("GetFooFor", typeof(ExpectedBar)))
   .With(prop1).Will(Return.Value(List<ExpectedBar>)); 

GetFooFor<UnExpectedBar>(prop1);

Here’s the matcher. Basically it uses reflection (MethodInfo). It caught us out at first as the first time it hits the matcher (when you set the expectation) as the method had not been made concrete (ContainsGenericParameters). It hits the Matcher again when the method gets called and voila the test fails.

public class GenericMethodMatcher : Matcher
{
    private readonly string methodName;
    private readonly Type expectedType;
    private string errortext = String.Empty;

    public GenericMethodMatcher(string methodName, Type expectedType)
    {
         this.methodName = methodName;
          this.expectedType = expectedType;
    }

    public override bool Matches(object o)
    {
        MethodInfo methodInfo = o as MethodInfo;

        if (methodInfo.Name == methodName)
        {
           //if this is true it means the method has not been called yet so will not have our argument yet.
           if (methodInfo.ContainsGenericParameters)
               return true;

           foreach (Type type in methodInfo.GetGenericArguments())
           {
               if (expectedType == type)
                   return true;
               }
               errortext = string.Format("Generic method{0} called with unexpected type parameter. Expected: {1} ", methodName, expectedType);
                   return false;
                }
                return false;
            }

            public override void DescribeTo(TextWriter writer)
            {
                Console.WriteLine(errortext);
            }
        }
    }
}
]]>