chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
Have a method:

static void DoSomething(ValueObject obj)
{

}


I need to swap so that I can verify a child property in 'obj' has been modified prior to this method being called in target method I'm calling (which calls this method).

This level of testing is required because it would be very easy for the code that modifies the child property of obj to be removed accidently and then there'd be no unit test that fails.

How do you swap static methods on static classes.

I have:

Isolate.Swap.CallsOn(typeof(StaticClass)).WithCallsTo(typeof(SwapStaticClass));

When running I get:

***Cannot swap MsCorLib type: System.RuntimeType

Which doesn't seem to be the correct message for this.

Using 5.2.3, upgrade not possible at this time.
asked by boo (21.8k points)

3 Answers

0 votes
Hi,

Duck typing feature supports instance methods only. The swap expects an object to route the calls from. In the example you posted, the object is System.RuntimeType of the StaticClass, therefor the error about swapping an MsCorLib type (this is the result of typeof operator).

You can route static calls using the DoInstead feature. For example:
public class Original
{
    public static void AddNumber(IList<int> number)
    {
        // RealCode
        number.Add(1);
    }
}

public class Target
{
    public static void FirstAction(IList<int> number)
    {
        // Swapped Code
        number.Add(2);
    }
}

[TestMethod]
public void SwapStaticMethod()
{
    Isolate.WhenCalled(() => Original.AddNumber(null))
        .DoInstead(context => Target.FirstAction(context.Parameters[0] as IList<int>));

    var numbers = new List<int>();
    Original.AddNumber(numbers);

    Assert.AreEqual(2, numbers[0]);
}


If all you want is to verify the order of calls, you can do it using the DoInstead functionality as well. For example:
public class Logger
{
    public static void Log()
    {
        // Log logic...
    }
}

public class ValueObject
{
    public int Value { get; set;}
}

public class ClassUnderTest
{
    public void SetAndLog(ValueObject valueObject)
    {
        valueObject.Value = 5;
        Logger.Log();
    }
}

[TestMethod]
public void VerifyStaticMethodWasCalledAfterPropertySet()
{
    bool wasSetterCalled = false;
    bool wasLogCalledBeforeSetter = false;

    Isolate.WhenCalled(() => Logger.Log())
        .DoInstead(context => wasLogCalledBeforeSetter = !wasSetterCalled);

    var fake = Isolate.Fake.Instance<ValueObject>();
    Isolate.WhenCalled(() => { fake.Value = 0; })
        .DoInstead(context => wasSetterCalled = true);

    var underTest = new ClassUnderTest();
    underTest.SetAndLog(fake);

    Assert.IsFalse(wasLogCalledBeforeSetter);
}


Please let me know if it helps.

Regards,
Elisha
Typemock Support Team
answered by Elisha (12k points)
0 votes
Is DoInstead part of 5.2.3? I thought that was a newer feature. Also what is the 'context' parameter is your example?
answered by boo (21.8k points)
0 votes
Hi,

The DoInstead is part of 5.2.3 API.

The context parameter is of type MethodCallContext. It represents the instance on which the call is made and the parameters that where sent.

The parameters properties is context.Parameters. Parameters is an array of objects, where the first parameter is context.Parameters[0], the second is context.Parameters[1] and so on.

Best Regards,
Elisha
Typemock Support Team
answered by Elisha (12k points)
...