Modifying The Method Logic

You can modify the implementation of a mocked method, and when the method is called it will run the custom logic that you had entered.

When to Use

When you need to change the mocked method logic.

Syntax

C#

Isolate.WhenCalled(() => fake.<method>).DoInstead{()=>
 //your custom logic
};

VB

Isolate.WhenCalled(Function()  fake.<method>).DoInstead(Function()
 //your custom logic
)

How to Use

To run a custom logic in a faked method, use DoInstead after WhenCalled and provide your own delegate. DoInstead passes MethodCallContext with the following members:

Member

Description

Instance

An instance of the calling object (null if the method is static)

Parameters

Array of objects of the arguments passed to the method (if exist)

Method

A MethodBase object that contains method metadata that can be used for choosing the required behavior

ContinueFakingThisMethodRecursively

Boolean flag to enable and disable recursively faking method

WillCallOriginal()

Calls the original implementation

Samples

Sample 1:

The following sample shows the following:

DoInstead sends a custom delegate that will run when GetID is called.

The actual call to GetID will call the custom delegate.

Overloads for DoInstead also exist for void methods and non-public methods.

C#

// Note: Use Isolated to clean up after the test
[TestMethod, Isolated] 
public void DoInstead_Example()
{
  var returnValue = 2;
  var fakeDependency = Isolate.Fake.Instance<Dependency>();
  // return value dynamically
  Isolate.WhenCalled(() => fakeDependency.GetID()).DoInstead(
  x => { return returnValue; });

  returnValue = 4;
  var result = new ClassUnderTest().AddToDependency(1, fakeDependency);

  Assert.AreEqual(5, result);
}

public int AddToDependency(int a, Dependency dependency)
{
  return a + dependency.GetID();
}

VB

' Note: Use Isolated to clean up after the test
<TestMethod(), Isolated()> 
Public Sub DoInstead_Example()
      Dim returnValue = 2
      Dim fakeDependency = Isolate.Fake.Instance(Of Dependency)()
      ' return value dynamically
      Isolate.WhenCalled(Function() fakeDependency.GetID()).DoInstead(Function(x)
                                                                Return returnValue

                                                            End Function)

      returnValue = 4
      Dim result = New ClassUnderTest().AddToDependency(1, fakeDependency)

      Assert.AreEqual(5, result)
  End Sub
  
Public Function AddToDependency(a As Integer, dependency As Dependency) As Integer
    Return a + dependency.GetID()
End Function

Sample 2: Running Custom Logic and Continuing with the Original Method

The following example shows how to apply a custom logic and then continue with the implementation of the original method.

C#

[TestMethod, Isolated]
public void WhenCalledDoInstead_RunOriginalAfterLogic()
{
  var fakeDependency = new Dependency();
  int counter = 0;
  Isolate.WhenCalled(() => fakeDependency.Calculate()).DoInstead(
  c =>
  {
  // Custom logic before original call
  counter++;
  // Make sure the method gets called immediately after leaving
  c.WillCallOriginal();
  return null;
  });
  fakeDependency.Calculate();
  Assert.IsTrue(counter == 1);
}

VB

<TestMethod(), Isolated()>
  Public Sub WhenCalledDoInstead_RunOriginalAfterLogic()
      Dim fakeDependency = New Dependency()
      Dim counter As Integer = 0
      Isolate.WhenCalled(Function() fakeDependency.Calculate())
	   .DoInstead(Function(c)
                 ' Custom logic before original call
                 counter += 1
                 ' Make sure the method gets called immediately after leaving
                 c.WillCallOriginal()
                 Return Nothing

               End Function)
      fakeDependency.Calculate()
      Assert.IsTrue(counter = 1)
  End Sub

Sample 3: Calling the Original Method but with another arguments

The following example shows how to change an argument and then continue with the implementation of the original method.

If it's possible, Typemock makes an implicit conversion of an arguments.

C#
public class Dependency
{
  public int Increment(int i)
  {
    return i + 1;
  }
}

[TestMethod, Isolated]
public void WhenCalledDoInstead_RunOriginalAfterLogic()
{
  var fakeDependency = new Dependency();
  Isolate.WhenCalled(() => fakeDependency.Increment(0)).DoInstead(
  c =>
  {
  // Changing argument before original call
  c.Parameters[0] = 100;
  // Make sure the method gets called immediately after leaving
  c.WillCallOriginal();
  return null;
  });
  var res = fakeDependency.Increment(1);
  Assert.IsTrue(res == 101);
}

VB
Public Class Dependency
    Public Function Increment(i As Integer) As Integer
        Return i + 1
    End Sub
End Class

<TestMethod(), Isolated()>
  Public Sub WhenCalledDoInstead_RunOriginalAfterLogic()
      Dim fakeDependency = New Dependency()
      Isolate.WhenCalled(Function() fakeDependency.Increment(0))
	   .DoInstead(Function(c)
                 ' Changing argument before original call
                 c.Parameters(0) = 100
                 ' Make sure the method gets called immediately after leaving
                 c.WillCallOriginal()
                 Return Nothing
               End Function)
      Dim res = fakeDependency.Increment(1)
      Assert.IsTrue(res = 101)
  End Sub

Sample 4: Running Custom Logic in Recursion

The following example shows how to use ContinueFakingThisMethodRecursivly flag.
By default, with the first hit of DoInstead() block faking for beahavior is done. To create more complex, recursion-based logic for DoInstead(), you need to enable it be setting ContinueFakingThisMethodRecursivly flag to true.

C#

public class Dependency
{
  public void DoStuff(int i)
  {
    throw new NotImplementedException();
  }
}

public class ClassForRecursion
{
  public int count = 0;
  private Dependency dependency;

  public ClassForRecursion(Dependency dependency)
  {
    this.dependency = dependency;
  }

  public void Foo(int i)
  {
    count++;
    if (i < 5)
    {
    dependency.DoStuff(i);
    }
  }
}

[TestMethod, Isolated]
public void DoInstead_WithRecursion()
{
  var dependency = new Dependency();
  var classForRecursion = new ClassForRecursion(dependency);

  Isolate.WhenCalled(() => dependency.DoStuff(0)).DoInstead(
    context =>
    {
      int passedVal = (int) context.Parameters[0];
      context.ContinueFakingThisMethodRecursively = true;
      classForRecursion.Foo(passedVal + 1);
    }
  );

  classForRecursion.Foo(1);

  Assert.AreEqual(5, classForRecursion.count);
}

VB

Public Class Dependency
    Public Sub DoStuff(i As Integer)
        Throw New NotImplementedException()
    End Sub
End Class

Public Class ClassForRecursion
    Public count As Integer = 0
    Private dependency As Dependency

    Public Sub New(dependency As Dependency)
        Me.dependency = dependency
    End Sub

    Public Sub Foo(i As Integer)
        count += 1
        If i < 5 Then
            dependency.DoStuff(i)
        End If
    End Sub
End Class

<TestMethod(), Isolated()>
Public Sub DoInstead_WithRecursion()
        Dim dependency = New Dependency()
        Dim classForRecursion = New ClassForRecursion(dependency)

        Isolate.WhenCalled(Sub() dependency.DoStuff(0)).
		 DoInstead(Sub(context)
                     Dim passedVal As Integer = CInt(context.Parameters(0))
                     context.ContinueFakingThisMethodRecursively = True
                     classForRecursion.Foo(passedVal + 1)

                 End Sub)

        classForRecursion.Foo(1)

        Assert.AreEqual(5, classForRecursion.count)
    End Sub