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.