Direct discussion with our users in our forums is immensly helpful when building our products; it brings out points that seem trivial to us but confusing to our users, which lets us know what should we simplify and improve on.
A recent thread started with a user posting some test code that did not work as expected. After skimming through the code, I noticed the problem – the user was using an incorrect technique to inject faked behavior into the code under test. This is something I would like to shed some light on as it can clear up a lot when writing tests. Generally speaking, Typemock Isolator provides us with means to fake behavior using the ISolate.WhenCalled() API. Using WhenCalled() we can fake a call’s return value, make it throw an exception or create a recursive fake. However, faking behavior is not enough when setting up our tests: we still need the code under test to receive this faked behavior somehow.
There are three ways to inject faked behavior to code under test, and each should be used in a specific scenario:
- If the code under test receives a reference to the object being faked:
public void MethodBeingTested(ISomething something)
{
int res = something.Do();
…
}
We simply pass the fake object to he code under test. For instance:
var fake = Isolate.Fake.Instance<ISomething>();
Isolate.WhenCalled(() => fake.Do()).WillReturn(5);
// now call the method under test
MethodBeingTested(fake);
- If the code under test receives the object we want to fake from a third party (i.e. from a call to another object):
ISomething something = ThirdParty.GetSomething();
int rest = something.Do();
…
we fake that third party to make it return our fake object complete with its faked behavior:
var fake = Isolate.Fake.Instance<ISomething>();
Isolate.WhenCalled(() => fake.Do()).WillReturn(5);
// the next the ThirdParty.GetSomething() is called we want to return the fake object
Isolate.WhenCalled(() => ThirdParty.GetSomething()).WillReturn(fake);
- Last but not least, in case the object under test creates a new instance of the object we would like to fake:
ISomething something = new Something();
int res = something.Do();
…
We use FakeNextInstance() to intercept the construction and replace the new object with our fake object:
var fake = Isolate.Fake.Instance<Something>();
Isolate.WhenCalled(() => fake.Do()).WillReturn(5);
// the next time Something is created we will swap it with fake
Isolate.Swap.NextInstance<Something>().With(fake);
As you can see, there’s a tool for every task, and in my experience it gets pretty simple once you practice using the API. Think I missed explaining a usage pattern? Got any other usage questions? Go ahead and ask them in the comments or on our forums – that’s what they’re for!