Release Notes

Version 5.3

These are the release notes for Release 5.3.


Exact Argument Matching
Call behavior can now be set to only happen when all arguments passed to WhenCalled() match those that are passed to the method in the call under test. This is done using the new WithExactArguments() completing statement. This way conditional method behavior can be set:
    // Using the c# API

    var
     fake = Isolate.Fake.Instance<ClassToIsolate>();
    // MethodReturnInt will return 10 when called with arguments 3, "abc"
    Isolate.WhenCalled(()=> fake.MethodReturnInt(3, "abc")).WithExactArguments().WillReturn(10);
    // MethodReturnInt will return 50 when called with arguments 3, "xyz"
    Isolate.WhenCalled(()=> fake.MethodReturnInt(3, "xyz")).WithExactArguments().WillReturn(50);

    // Method return value are conditional on the passed arguments
    Assert.AreEqual(10, fake.MethodReturnInt(3, "abc"));
    Assert.AreEqual(50, fake.MethodReturnInt(3, "xyz"));

    ' Using the VB Friendly API
    Dim Fake As ClassToIsolate = FakeInstance(Of ClassToIsolate)()

    ' MethodReturnInt will return 10 when called with arguments 3, "abc"
    Using TheseCalls.WithExactArguments.WillReturn(10)
       Fake.MethodReturnInt(3, "abc")
    End Using

    ' MethodReturnInt will return 50 when called with arguments 3, "xyz"
    Using TheseCalls.WithExactArguments.WillReturn(50)
       Fake.MethodReturnInt(3, "xyz")
    End Using

    ' Method return value are conditional on the passed arguments
    Assert.AreEqual(50, Fake.MethodReturnInt(3, "xyz"))
    Assert.AreEqual(10, Fake.MethodReturnInt(3, "abc"))
Redefining Methods
Call behavior can now be set with custom behavior. This is set by using the new DoInstead() completing statement:
    // Using the c# API

    var fake = Isolate.Fake.Instance<ProductShelf>();

    // When GetProductQuantity will be called, our anonymous delegate will run.
    // GetProductQuantity will return the value based on the custom logic inside the delegate.
    Isolate.WhenCalled(()=> fake.GetProductQuantity("")).DoInstead(callContext=>
    {
        // Access method arguments
        string name = callContext.Parameters[0] as string;
        if(name == "MyProduct")
        {
            return 10;
        }
        return 5;
    });

    // Assert - out custom behavior is returned when the method is called

    Assert.AreEqual(10, (int)fake.GetProductQuantity("MyProduct"));
    Assert.AreEqual(5, (int)fake.GetProductQuantity("OtherProduct"));


    ' Using the VB Friendly API
    ' VB.NET lacks full anonymous delegate support, so the API is demonstrated here by using AddressOf
    Dim fake As ProductShelf = FakeInstance(Of ProductShelf)()

    ' When GetProductQuantity method well be called our anonymous delegate will run.
    ' GetProductQuantity method will return the value based on the custom logic inside the delegate.
    Using TheseCalls.WillBeReplacedWith(AddressOf FunctionThatReplaceGetProductQuantity)
        fake.GetProductQuantity("")
    End Using

    ' Assert - our delegate runs
    Assert.AreEqual(10, CInt(fake.GetProductQuantity("MyProduct")))
    Assert.AreEqual(5, CInt(fake.GetProductQuantity("OtherProduct")))

    ' This is the custom behavior supplied to WillBeReplaced
    Public Function FunctionThatReplaceGetProductQuantity(ByVal callContext As MethodCallContext) As UInt32
        ' We can get the method arguments
        Dim name As String = TryCast(callContext.Parameters(0), String)
        If name = "MyProduct" Then
            Return 10
        End If

        Return 5
    End Function
Specific Constructor Invocation
When creating fake objects you can now control whether or not the original constructor of the type will be called, and with which parameters. Specifying constructor behavior in Isolate.Fake.Instance<T>() is done by providing it with either ConstructorWillBe.Called or ConsturctorWillBe.Ignored. If the behavior is ConstructorWillBe.Called, you can pass in consturctor arguments if any:
    // Using the c# API

    // The constructor is not faked here.
    ' We are passing the arguments (100, "Foo") to the constructor   
    var
     fake = Isolate.Fake.Instance<Person>(Members.ReturnRecursiveFakes, ConstructorWillBe.Called, 100, "Foo");   


    ' Using the VB Friendly API

    ' The constructor is not faked here.
    ' We are passing the arguments (100, "Foo") to the constructor
    Dim fake As Person = FakeInstance(Of Person)(Members.ReturnRecursiveFakes, ConstructorWillBe.Called, 100, "Foo")
Argument Matching Using Placeholders
Call behavior can now be set to only happen the arguments passed to the method match criteria defined on placeholders used in WhenCalled(). This way you can define custom conditional method behavior:
    var fake = Isolate.Fake.Instance<ClassToIsolate>();
    // Use argument placeholders to define conditional behavior on MethodReturnInt() -
    // only apply the custom behavior when the first argument is less than 5 and the second starts with "ab"

    Isolate.WhenCalled((int i, string s)=> fake.MethodReturnInt(i, s)).
        AndArgumentsMatch((i, s) => i > 5 && s.StartsWith("ab")).
        WillReturn(10);

    // Calling the method with arguments matching the custom matching function will return 10
    Assert.AreEqual(10, fake.MethodReturnInt(3, "abc"));
    // If one or more of the arguments fail the custom matching function the method will return the defualt value of 0
    Assert.AreEqual(0, fake.MethodReturnInt(10, "abc"));

Faking Base Class Constructor
It's now possible to control base class constructor behavior when creating fake objects. You can select whether to call or ignore a base class constructor, and choose whether to fake the immediate constructor or one higher up the inheritance chain:
    // Using the c# API
    // Create a fake instance of the Derived class, calling its original constructor while ignoring its base class constructor

    var fake1 = Isolate.Fake.Instance<Derived>(Members.CallOriginal, ConstructorWillBe.Called,
                                               BaseConstructorWillBe.Ignored);

    // Create a fake instance of the Derived class, calling its original constructor and and base class constructors up to the Base class.
    // This means the original constructor will be called as well as any the constructor for any class Derived derives from, until the constructor for
    // Base is encountered. Any constructor from the point onwards is faked.
    var fake2 = Isolate.Fake.Instance<Derived>(Members.CallOriginal, ConstructorWillBe.Called,
                                               BaseConstructorWillBe.Ignored, typeof(Base));


    ' Using the VB Friendly API
    ' Create a fake instance of the Derived class, calling its original constructor while ignoring its base class constructor

    Dim fake1 As Derived = FakeInstance(Of Derived)(Members.CallOriginal, ConstructorWillBe.Called,
                                                    BaseConstructorWillBe.Ignored)

    ' Create a fake instance of the Derived class, calling its original constructor and and base class constructors up to the Base class.
    ' This means the original constructor will be called as well as any the constructor for any class Derived derives from, until the constructor for
    ' Base is encountered. Any constructor from the point onwards is faked.
    Dim fake1 As Derived = FakeInstance(Of Derived)(Members.CallOriginal, ConstructorWillBe.Called,
                                                    BaseConstructorWillBe.Ignored, GetType(Base))

Fake All Instances of a Type
You can now define fake behavior for all existing or future instances of a type using the Swap.AllInstances() API:
    // Using the c# API
    // Create a fake instance of the product class and set behavior on CalculatePrice():

    var fake = Isolate.Fake.Instance<Product>();
    Isolate.WhenCalled(()=> fake.CalculatePrice(0)).WillReturn(100);

    // Here we are setting the same behavior on all instances.
    // The behavior we set on fake will apply to all instances so both product1 and product2 will have the same behavior.
    Isolate.Swap.AllInstances<Product>().With(fake);

    // instance created after the fake
    Product product1 = new Product();
    Product product2 = new Product();

    // Assert that the behavior applied to all instances.
    Assert.AreEqual(100, product1.CalculatePrice(0));
    Assert.AreEqual(100, product2.CalculatePrice(0));

    ' Using the VB Friendly API
    Dim fake As Product = FakeInstance(Of Product)()

    Using TheseCalls.WillReturn(100.0F)
        fake.CalculatePrice(0)
    End Using

    ' Here we are setting the same behavior on all instances.
    ' The behavior we set on fake will apply to all instances so both product1 and product2 will have the same behavior.
    SwapAllInstances(Of Product)(fake)

    ' instance created after the fake
    Dim product1 As New Product()
    Dim product2 As New Product()

    ' Assert that the behavior applied to all instances.
    Assert.AreEqual(100.0F, product1.CalculatePrice(0))
    Assert.AreEqual(100.0F, product2.CalculatePrice(0))

Explicit Method Invocation
Typemock Isolator now offers a way to help you  invoke private methods under test. This is done by using the Isolate.Invoke.Method() API:
    // Invoke a private method with 3 arguments
    var result = Isolate.Invoke.Method(targetObject, "InternalCalculateWorth", someProductInstance, 2, 5);
Event Invocation
Another new feature to help test events is the ability to invoke events through the Isolate.Invoke.Event() API:
    // Invoke an event which receives an integer argument
    Isolate.Invoke.Event(() => logger.LogEntryCreated += null, 1);
MSCorLib support:
Faking DateTime.Now
Faking File.ReadAllText()
This feature was requested by our users for a while now - faking DateTime.Now and other mscorlib types. Now you can fake DateTime.Now and File.ReadAllText - here's an example for DateTime.Now:
    // Fake calls to DateTime.Now to return January 1st 2008:
    Isolate.WhenCalled(() => DateTime.Now).WillReturn(new DateTime(2008, 1, 1));

    Assert.AreEqual(new DateTime(2008,1,1), DateTime.Now);
Improved Visual Studio integration
The Typemock menu has moved from under the Tools menu to our very own Typemock menu in the main Visual Studio toolbar, and we've added our Quick Start guide to the Help menu.


General fixes

In 5.3.5:

  • Major improvement to verification error messages - now the expected and actual values are printed out, as well as clear indication of which of them mismatch.
  • Fixed ref and out parameter behavior with Recursive Fakes

In 5.3.4:

  • Fixed a bug causing the Visual Studio WCF client test wizard fail if Isolator is enabled
  • Improved error message when trying to run on Windows 7 or Vista in Visual Studio without elevated privileges
  • Two major issues with generics are now resolved: support of faking classes with generic constraints, and proper handling of methods with complex generic return type
  • True property improvements: proper handling of recursive fakes' true properties, and fixed an issue  when mixing true property and WhenCalled() on the same property
  • Fixed bug that caused crash when generic method had the same name as a non generic method.

In 5.3.1:

  • Several issues involving resolving generic methods and types have been resolved
  • It is now possible to set more than one  behavior on static calls defined on structs.
  • Fixed an issue with fakeing behavior on non public properties on generic and abstract types
  • Generic methods in test classes decorated by the [Isolated] attribute do not cause an exception anymore
  • Fixed a NullReferenceException when sequencing calls on live fakes
  • Field values are now properly copied from the swapped instance to the swapping fake when using Swap.NextInstance()
  • Fixed an issue loading the Isolator Visual Studio add-in within localized editions of Visual Studio on English operating systems
  • Fixed an issue faking XElement behavior in the VB Friendly API

In 5.3:

  • Support is added to NCover 3 profiling (strarting NCover 3.0.18) 
  • Major improvements to the way generic methods are handled, including several bug fixes
  • Sequencing the WillThrow() call behavior caused exception to be thrown


Known Issues
  • Isolator now installs into Program Files->Typemock->Isolator->5.3. When removing former versions, some artifcats on the file system and menus may remain, which can be deleted manually. 
  • Isolator AAA does not support nested chains in WhenCalled() and Verify methods:
  • Isolate.WhenCalled(() => fake.Call(fake.Do())).WillReturn(0); // not supported

    // instead extract the inner chain to a variable:
    var innerChain = fake.Do();
    Isolate.WhenCalled(() => fake.Call(innerChain)).WillReturn(0); // supported


Breaking changes
N/A


 

Copyright © Typemock Ltd. 2004-2020. All Rights Reserved.