telandor
telandor

Reputation: 869

Fake extension method using exact arguments

I am writing tests for our C# 7 application and struggle with mocking an Extension method. I am using TypeMock 8.6.10.3.

Here is a simplified example:

internal class InnerClass
{
  private readonly string _description;

  public InnerClass(string description)
  {
    _description = description;
  }

  public string GetDescription()
  {
    return _description;
  }
}

internal class OuterClass
{  
  public void DoSthWithExtension(int someNumber)
  {
    var innerClass = new InnerClass("InnerClassDescription");
    innerClass.Extension(someNumber);
  }
}

internal static class Extensions
{
  public static void Extension(this InnerClass innerClass, int someNumber)
  {
    var d = innerClass.GetDescription();
  }
}

 public void TestExtension()
{
  // I want to fake the method "InnerClass.Extension()"
  // which is called by "OuterClass.DoSthWithExtension()".
  // I don't have access to the InnerClass instance though.
  // So unfortunately I have to fake them all.
  var fakedInnerClasses = Isolate.Fake.AllInstances<InnerClass>();

  Isolate.WhenCalled(() => Extensions.Extension(fakedInnerClasses, 11)).WithExactArguments().DoInstead(
    c =>
    {
      // The test doesn't go in here. The second parameter is correct,
      // the first one obviously not. But what is expected as a first parameter then?

      var oc2 = new OuterClass();

      // Here I call InnerClass.Extension() again.
      // The test should now go into the faked method underneath.
      oc2.DoSthWithExtension(22);
    });

  Isolate.WhenCalled(() => Extensions.Extension(fakedInnerClasses, 22)).WithExactArguments().DoInstead(
    c =>
    {
      // As above, the test code doesn't go in here.
    });

  // In here an instance of InnerClass is created and
  // InnerClass.Extension(11) is called.
  var oc1 = new OuterClass();
  oc1.DoSthWithExtension(11);
}

As the this parameter of the Extension method I choose the faked instances of InnerClass. Thats what I assume is needed. But TypeMock does not bring me into the faked method. Obviously its the wrong parameter. But which one should I choose then?

Upvotes: 0

Views: 151

Answers (1)

Nkosi
Nkosi

Reputation: 247581

Based on comments and updated question, the part that is confusing is why the other outer class is needed. The shown inner class has no dependency on the outer. Why would the mock then need to create a new outer class?

That aside, based on the docs its appears that you need to setup the extension class so that you can fake the static extension calls.

Isolate.Fake.StaticMethods(typeof(Extensions));

//...

Original answer

Do not fake the extension method in this case. You know what the extension method calls. so fake that.

public void TestExtension() {
    //Arrange
    string expected = "Fake result";
    var fakedInnerClasses = Isolate.Fake.AllInstances<InnerClass>();
    Isolate.WhenCalled(() => fakedInnerClasses.GetDescription())
        .WillReturn(expected);

    var subject = new OuterClass();

    //Act
    subject.DoSthWithExtension();
    
    
    //Assert
    //...
}

So now when the outer is called and the extension method invoked, it will be acting on the mock controlled by you.

Upvotes: 1

Related Questions