2. • Open-source .NET dynamic fake framework (http://fakeiteasy.github.io/)
• Constrained (inheritance based)
• Can be freely downloaded from GitHub:
https://github.com/FakeItEasy/FakeItEasy
• Has a NuGet Package
FakeItEasy
3. • No need to write & maintain fake objects
• Helpful exception messages identify where a test went wrong
• Simple AAA fluent interface
– Single point of entry: “A.”
– Explicit assertions
• Default behavior is usually the desired behavior
• Flexible parameter handling
• Refactoring safe
Benefits
5. • Interfaces
• Classes
– Not sealed
– Not static
– Have at least one public/protected c’tor that FakeItEasy can
create or obtain
What types can be faked
6. Since FakeItEasy fake by creating a derived class only the following
methods/properties can be faked:
• Virtual
• Abstract
• Defined on an interface
The following can not be faked:
• Static
• Extension
• Non-virtual or Sealed
What members can be overridden
7. var fakeDependency = A.Fake<IDependency>();
Creating fake objects
Remember: c’tor will be called when creating a fake
Solution: Assign specific arguments to the c’tor – in a strongly typed way
A.Fake<DependencyClass>(x => x.WithArgumentsForConstructor(() => new DependencyClass(p1)));
A.Fake<DependencyClass>(x => x.OnFakeCreated((c => c.Method1())));
Define a method to run after object created
A.Fake<DependencyClass>(x => x.Implements(typeof(IOther)));
Specify additional interfaces to be implemented. Useful when fake skips memebers because they have
been explicitly implemented on the faked class
And more - https://github.com/FakeItEasy/FakeItEasy/wiki/Creating-Fakes
8. • Caution: Non-overideable methods call original
implementation
• Methods automatically return:
– string string.Empty
– Non-fakeable types (incl. value-types) default(T)
– Fakeable T Fake of T
• Unless told otherwise (usually not a good idea)
Default behavior
var fake = A.Fake<IDatabase>(builder => builder.Strict());
9. Use A.CallTo to define behavior on method/property or object
Setting behavior on fake objects
Specify behavior to all methods and properties (return null if not void)
A.CallTo(fakeDependency).DoesNothing();
Specify return value for single method
A.CallTo(() => fakeDependency.SomeMethod()).Returns(42);
A.CallTo(() => fakeDependency.SomeMethod()).DoesNothing();
Throw exception
A.CallTo(() => fakeDependency.SomeMethod()).Throws<ApplicationException>();
A.CallTo(() => fakeDependency.SomeMethod()).Throws(new ApplicationException("Boom!"));
Invoke custom code
A.CallTo(() => fakeDependency.SomeMethod()).Invokes(() => otherClass.Method());
10. Although can set properties using A.CallTo there’s an easier and simpler way.
Setting a value on any fakeable property would cause its getter to return
the same value
Read Write property behavior (auto property)
var fakeDependency = A.Fake<IDependency>();
fakeDependency.SomeProperty = 5;
Console.Out.WriteLine(fakeDependency.SomeProperty); // print 5
11. • Uses exactly the same syntax as setting behavior
• Following by MustHaveHappened/MustNotHaveHappened
Asserting methods were called
// Asserting that a call has happened at least once.
// The following two lines are equivalent.
A.CallTo(() => foo.Bar()).MustHaveHappened(Repeated.AtLeast.Once); // or
A.CallTo(() => foo.Bar()).MustHaveHappened();
// To contrast, assert that a call has happened exactly once.
A.CallTo(() => foo.Bar()).MustHaveHappened(Repeated.Exactly.Once);
// Asserting that a call has not happened.
// The following two lines are equivalent.
A.CallTo(() => foo.Bar()).MustNotHaveHappened(); // or
A.CallTo(() => foo.Bar()).MustHaveHappened(Repeated.Never);
Caution: test results and not method calls to avoid fragile tests
12. When using actual values these values would be checked before setting
behavior or verifying calls.
Specific arguments constraints when for behavior are over-specification and
should be avoided (usually):
A.CallTo(() => foo.Bar("hello", 17)).Returns(true);
Specific arguments constraints for verify means that we want to make sure that
the method was called/not called with these specific arguments:
A.CallTo(() => foo.Bar("hello", 17)).MustHaveHappened();
Argument Constraints – match exactly
13. Recommended when setting behavior:
A.CallTo(() => foo.Bar(A<string>.Ignored, A<int>.Ignored)).Returns(true);
Can use ‘_’ as a shorthand
A.CallTo(() => foo.Bar(A<string>._, A<int>._)).Returns(true);
For complicated constraints use “that” method:
A.CallTo(
() => foo.Bar(A<string>.That.IsEmpty(), A<int>.That.IsGreaterThan(0))).Returns(true);
Or use custom constraints –
https://github.com/FakeItEasy/FakeItEasy/wiki/Argument-Constraints
Argument Constraints – match Any arguments
14. Raise event from fake object
Used in tests of functionality that is triggered by an event
Raising events
// Raise the event!
fake.OnEvent += Raise.With(EventArgs.Empty).Now;
// Use the overload for empty event args
fake.OnEvent += Raise.WithEmpty().Now;
// Specify sender explicitly:
fake.OnEvent += Raise.With(sender: robot, e: EventArgs.Empty).Now;
15. Can create a value that changes over time
Setting behavior that change over time
// Return according to sequalnce until finished
// Afterwards will not take an item from the sequence,
// but will rely on other configured (or default) behaviour
A.CallTo(() => fake.Count).ReturnsNextFromSequence(1,2,3,5,8,12,20);
// Returns the number of times the method has been called
int counter = 0;
A.CallTo(() => fake.Count).ReturnsLazily(() => ++counter);
// set up an action that can run forever, unless superseded
A.CallTo(() => fake.Bar()).Returns(true);
// set up a one-time exception which will be used for the first call
A.CallTo(() => fake.Bar()).Throws<Exception>().Once();
Setting behavior on same method several times creates a call sequence
Caution: Use sparsely, usually an over-specification fragile tests
16. Should not be used frequently – remember the “single assert per test rule” -
only use when the order is the assertion.
• Example: read from DB before data was updated.
Ordered assertions
using (var scope = Fake.CreateScope())
}
// Act
worker.JustDoIt();
// Assert
using (scope.OrderedAssertions())
}
A.CallTo(() => unitOfWorkFactory.BeginWork()).MustHaveHappened();
A.CallTo(() => usefulCollaborator.JustDoIt()).MustHaveHappened();
A.CallTo(() => unitOfWork.Dispose()).MustHaveHappened();
}
{
17. Add the following to the AssembltInfo.cs file in the Assembly under test:
• [assembly: InternalsVisibleTo(“test assembly name”)] for the type to be
visible to the test assembly
• [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2,
PublicKey=00240000048000009400000006020000002400005253413100
04000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc98916
05d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0
bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46
ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be1
1e6a7d3113e92484cf7045cc7“)]
Faking internal objects
18. Dependency injection
How can we pass the fake object to the production code?
• Factory method/class
• Constructor/property Injection
• Object locator pattern
19. Things to remember when using FakeItEasy
1. Code to interfaces (LSP)
2. Declare methods as virtual
3. Use dependency injection