Using FakeIteasy


Published on

A quick introduction to FakeItEasy - an open source mocking framework for .NET

Published in: Software, Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Using FakeIteasy

  1. 1. Using FakeItEasy Dror Helper Senior consultant | | @dhelper
  2. 2. • Open-source .NET dynamic fake framework ( • Constrained (inheritance based) • Can be freely downloaded from GitHub: • Has a NuGet Package FakeItEasy
  3. 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
  4. 4. Use NuGet to get latest version
  5. 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. 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. 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 -
  8. 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. 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. 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. 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. 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. 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 – Argument Constraints – match Any arguments
  14. 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. 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. 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. 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. 18. Dependency injection How can we pass the fake object to the production code? • Factory method/class • Constructor/property Injection • Object locator pattern
  19. 19. Things to remember when using FakeItEasy 1. Code to interfaces (LSP) 2. Declare methods as virtual 3. Use dependency injection
  20. 20. Dror Helper C: 972.05.7668543 e: B: w: