Faking Future Instances


Fake objects cannot always be injected into the code under test. Sometimes the code under test instantiates an object which we would like to fake the behavior of in runtime  ('future instance'). These objects can be set up as fake objects using the creation techniques above, and set up to be swapped with the future object at the time of its creation. This is done using the Isolate.Swap.NextInstance().With() method.

This example shows creating a fake object, setting it to be swapped with a future instance and setting up its behavior:
[TestMethod]
[Isolated]
public void FutureInstance_VerifyMethodWasCalledAndStubbed ()
{
    // Arrange
    RealLogger fake = Isolate.Fake.Instance<RealLogger>();
    // replace a future instance of RealLogger with the fake object we created
    Isolate.Swap.NextInstance<RealLogger>().With(fake);
    // set up additional fake object behavior
    Isolate.WhenCalled(() => fake.Increment()).IgnoreCall();

    // Act
    RealLogger real = new RealLogger(); // at this point the fake object replaces the future instance
    real.Increment();

    // Assert
    Isolate.Verify.WasCalledWithAnyArguments(() => fake.Increment());
}

In case you want to simulate an error while constructing an object, you can use the future instance pattern to thrown an exception from the next constructor call to the type. This is done using the Isolate.Swap.NextInstance().ConstructorWillThrow() method.

This example shows declaring that an object's creation will throw an exception, and verifying that a factory method creating this type throws the exception:
[TestMethod]
[Isolated]
[ExpectedException(typeof(OutOfMemoryException))]
public void FutureInstance_VerifyThrowingExceptionOnCreation ()
{
    // We want a memory handling exception to be thrown the next time a RealLogger is instantiated
    Isolate.Swap.NextInstance<RealLogger>().ConstructorWillThrow(new OutOfMemoryException());
   
    LoggerFactory.CreateRealLogger(); // this call instantiates a new RealLogger, and should throw an exception
}

Setting Behavior on All Instances

When you want to set the same behavior on all instances of a certain type you should use Isolate.Swap.AllInstances method.
This will set the specified behavior on all past and future instances of the same type.

Example:
[TestMethod, Isolated]
public void SwapAllInstances_TwoFutureInstances_AllInstancesAreFakes()
{
    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);

    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));
}

You can use Isolate.Swap.AllInstances to set expectations on instances that were created before the test runs (for example in the test class set up method).
The following examples shows how to fake behavior of the singleton pattern:
public class Singleton
{
    private Singleton()
    {

    }

    static readonly Singleton instance = new Singleton();

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }

    public int ReturnZero()
    {
        return 0;
    }
}

The test method uses Isolate.Swap.AllInstances to replace the singleton object with a fake object that has specific bahvior:
[TestMethod]
public void SwapAllInstances_Singleton_SingletonFaked()
{
    var fakeSingleton = Isolate.Fake.Instance<Singleton>();
    Isolate.WhenCalled(() => fakeSingleton.ReturnZero()).WillReturn(10);

    // Here we are setting the same behavior on all instances.
    // The behavior we set on fake will apply to past instance as well
    Isolate.Swap.AllInstances<Singleton>().With(fakeSingleton);

    // Assert that the behavior applied to all instances.
    Assert.AreEqual(10, Singleton.Instance.ReturnZero());
}


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