Advanced usage
FakeItEasy exposes a few APIs that aren't commonly needed, but can be useful in certain scenarios.
Clearing the configuration of a fake
The Fake.ClearConfiguration
method removes all configured rules from a fake, leaving it in the default configuration.
var foo = A.Fake<IFoo>();
Assert.Equal(0, foo.Bar());
A.CallTo(() => foo.Bar()).Returns(42);
Assert.Equal(42, foo.Bar());
Fake.ClearConfiguration(foo);
Assert.Equal(0, foo.Bar());
Clearing a fake's recorded calls
The Fake.ClearRecordedCalls
method clears all recorded calls from a fake. Subsequent call assertions won't see these calls.
var foo = A.Fake<IFoo>();
foo.Bar();
A.CallTo(() => foo.Bar()).MustHaveHappened();
Fake.ClearRecordedCalls(foo);
A.CallTo(() => foo.Bar()).MustNotHaveHappened();
Getting the list of calls made on a fake
Sometimes, the call assertion API offered by FakeItEasy isn't enough, and you need to manually check the calls made on a fake.
The Fake.GetCalls
method returns a fake's recorded calls as a list of ICompletedFakeObjectCall
objects that you can examine yourself:
var foo = A.Fake<IFoo>();
foo.Bar();
foo.Baz();
var calls = Fake.GetCalls(foo).ToList();
Assert.Equal(2, calls.Count);
Assert.Equal("Bar", calls[0].Method.Name);
Assert.Equal("Baz", calls[1].Method.Name);
The FakeManager
object
The Fake.GetFakeManager
method returns a FakeManager
object that can be used to get information on the fake and manipulate its call rules.
Getting the type of the fake
The FakeManager.FakeObjectType
property returns the type of the fake, i.e. the type that was passed to A.Fake
. This can be useful
if you're writing code that dynamically manipulates fakes.
var foo = A.Fake<IFoo>();
var manager = Fake.GetFakeManager();
Assert.Equal(typeof(IFoo), manager.FakeObjectType);
Getting the fake from the fake manager
The FakeManager.Object
property returns the fake object managed by this FakeManager
.
Manipulating a fake's call rules
The FakeManager.Rules
property returns all the rules configured on a fake.
var foo = A.Fake<IFoo>();
A.CallTo(() => foo.Bar()).Returns(42);
A.CallTo(() => foo.Baz()).DoesNothing();
var manager = Fake.GetFakeManager(foo);
var rules = manager.Rules.ToList();
Assert.Equal(2, rules.Count);
It is also possible to add custom rules for advanced scenarios, using AddRuleFirst
and AddRuleLast
. AddRuleFirst
adds a rule at the beginning of the rule list, so that it's considered before any other rule (which is the normal behavior when configuring a fake with A.CallTo(...)
). AddRuleLast
adds a rule at the end of the rule list, so that it's considered after any other rule.
class MyRule : IFakeObjectCallRule
{
public int? NumberOfTimesToCall => null;
public void Apply(IInterceptedFakeObjectCall fakeObjectCall)
{
fakeObjectCall.SetReturnValue(42);
}
public bool IsApplicableTo(IFakeObjectCall fakeObjectCall)
{
return fakeObjectCall.Method.DeclaringType == typeof(IFoo)
&& fakeObjectCall.Method.Name == "Bar";
}
}
...
var foo = A.Fake<IFoo>();
var manager = Fake.GetFakeManager(foo);
manager.AddRuleFirst(new MyRule());
Assert.Equal(42, foo.Bar());
You can also remove a rule using the RemoveRule
method.
Intercepting calls
Using the FakeManager.AddInterceptionListener
method, you can add a listener that is called every time a fake method is called.
class MyListener : IInterceptionListener
{
public void OnBeforeCallIntercepted(IFakeObjectCall interceptedCall)
{
Console.WriteLine($"A call to '{interceptedCall.Method}' is about to be processed");
}
public void OnAfterCallIntercepted(ICompletedFakeObjectCall interceptedCall)
{
Console.WriteLine($"A call to '{interceptedCall.Method}' has been processed");
}
}
...
var foo = A.Fake<IFoo>();
A.CallTo(() => foo.Baz()).Invokes(() => Console.WriteLine("Hello world"));
var manager = Fake.GetFakeManager(foo);
manager.AddInterceptionListener(new MyListener());
foo.Baz();
The code above prints: