left-icon

FakeItEasy Succinctly®
by Michael McCarthy

Previous
Chapter

of
A
A
A

CHAPTER 3

Introducing FakeItEasy

Introducing FakeItEasy


Before we start writing unit tests and using FakeItEasy, let’s start with a solid understanding of the framework. This chapter will focus on what can be faked, how different fakes can be created, how to feed constructor arguments to fakes, what members can be overridden by FakeItEasy, and default behavior “out of the box” when creating a fake.

What Can Be Faked?

Interfaces                                                       

Since many of the dependencies passed into classes are done so via interfaces, most of the time, you’ll be creating a fake for an interface.

Classes

There are times when you want to fake a class’s functionality. Classes can be injected into other classes as dependencies (although the preferred method is to use an interface). These are the types of classes that can be faked:

  • Classes that are not sealed
  • Classes that are not static
  • Classes that have at least one public or protected constructor whose arguments FakeItEasy can construct or obtain.

If we do try to fake a static class, this is what we’ll see:

You cannot fake a static class

Figure 13: You cannot fake a static class

Note that the compiler is already showing us an error. If you hover over the red underlined class name, you’ll see this error from the compiler:

The compiler won’t let you fake a static class

Figure 14: The compiler won’t let you fake a static class

If we try to fake a sealed class, unlike the static class, the compiler will not give us an error and will allow the code to compile. However, the unit test will still fail. Here is the class and the test for a static class:

public sealed class YouCannotFakeASealedClass

{

    public void DoSomething()

    {

        //some implementation

    }

}

[TestFixture]

public class WhenTryingToFakeASealedClass

{

    private YouCannotFakeASealedClass sut;

    [SetUp]

    public void Given()

    {

        sut = A.Fake<YouCannotFakeASealedClass>();

        sut.DoSomething();

    }

    [Test]

    public void ShouldNotDoAnything()

    {

        A.CallTo(() => sut.DoSomething()).MustHaveHappened(Repeated.Exactly.Once);

    }

}

Code Listing 15: A unit test for a sealed class

And here is the unit test failure:

Unit test failure trying to fake a sealed class

Figure 15: Unit test failure trying to fake a sealed class

Where do the constructor arguments come from?

WithArgumentsForConstructor

Here is how to pass arguments to your fake using WithArgumentsForConstructor:

public class AClassWithArguments

{

    private readonly string thisIsAnArgument;

    public AClassWithArguments(string thisIsAnArgument)

    {

        this.thisIsAnArgument = thisIsAnArgument;

    }

    public virtual void AFakeableMethod()

    {

        Console.Write(thisIsAnArgument);

    }

}

[TestFixture]

public class WhenFakingAClassWithArgumentsUsingWithArgumentsForConstructor

{

    private AClassWithArguments sut;

    [SetUp]

    public void Given()

    {

        sut = A.Fake<AClassWithArguments>(x => x.WithArgumentsForConstructor(

        () => new AClassWithArguments(A<string>.Ignored)));

        sut.AFakeableMethod();

    }

    [Test]

    public void ACallToAFakeableMethodMustHaveHappened()

    {

        A.CallTo(() => sut.AFakeableMethod()).MustHaveHappened();

    }

}

Code Listing 16: Passing arguments to a faked SUT

Note how we use A.Fake<T> to construct the fake using the class, but our lambda uses WithArgumentsForConstructor in order for FakeItEasy to get a “hook” into the values passed to the fake’s constructor.

Note: Don’t worry about A.string<Ignored> or MustHaveHappened yet. We’ll get to passing values to methods later in the book. For now, know that passing A<string>.Ignored into the fake’s method means we either don’t care about the value, or won’t be asserting against anything that the ignored value might affect for our unit tests. MustHaveHappened is a way to assert something has, or hasn’t happened in the configured fake. WithArgumentsForConstructor will be covered in-depth in Chapter 9, “Faking the Sut.”

What members can be overridden?

  • Virtual members
  • Abstract members
  • Interface method when an interface is being faked

Note that static members are missing from this list; they are not overridable.

Default Fake Behavior

This is behavior we get “out of the box” when we create a fake. We will be learning more about behavior of a fake later in the book, starting with Chapter 5, “Configuring Calls to a Fake.” For now, the following two sections will outline the behavior you get when simply creating a new fake.

Non-overridable members cannot be faked

What happens when we try to fake a non-overridable method on a class? Given the following class:

public class AClassWithAnUnfakeableMethod

{

    public void YouCantFakeMe()

    {

        //some implementation

    }

}

Code Listing 17: A class with an unfakeable method

And the following unit test for the class:

[TestFixture]

public class WhenTryingToFakeAndUnfakeableMethod

{

    private AClassWithAnUnfakeableMethod sut;

    [SetUp]

    public void Given()

    {

        sut = A.Fake<AClassWithAnUnfakeableMethod>();

        sut.YouCantFakeMe();

    }

    [Test]

    public void YouWillGetAnException()

    {

        A.CallTo(() => sut.YouCantFakeMe()).MustHaveHappened();

    }

}

Code Listing 18: Unit test for the unfakeable method

Note: Don’t worry about .MustHaveHappened or A.CallTo yet. We’ll cover both of these items in Chapter 7, “Assertions.”

When we run the unit test, it fails:

Unit test failing when trying to fake an non-overridable member

Figure 16: Unit test failing when trying to fake an non-overridable member

Note here that FakeItEasy is enforcing those out-of-the-box rules, and telling us specifically why we received an exception when we ran our unit test:

“The current proxy generator can not intercept the specified method for the following reason:  
- Non virtual methods can not be intercepted.

Overridable members can be faked

Let’s take our class above, change the YouCantFakeMe method to virtual, and rename it to YouCanFakeMe. Here is our class now:

public class AClassWithAFakeableMethod

{

    public virtual void YouCanFakeMe()

    {

        //some implementation

    }

}

Code Listing 19: YouCanFakeMe is now a fakeable method because it’s declared as virtual

And the updated unit test:

[TestFixture]

public class WhenTryingToFakeAFakeableMethod

{

    private AClassWithAFakeableMethod sut;

    [SetUp]

    public void Given()

    {

        sut = A.Fake<AClassWithAFakeableMethod>();

        sut.YouCanFakeMe();

    }

    [Test]

    public void YouCanFakeThisMethod()

    {

        A.CallTo(() => sut.YouCanFakeMe()).MustHaveHappened();

    }

}

Code Listing 20: The unit test for AClassWithAFakeableMethod

When we run the unit test, this is our output:

Unit test passing when method is declared as virtual

Figure 17: Unit test passing when method is declared as virtual

Note: Although we’ve allowed our unit test to pass by declaring YouCanFakeThisMethod as virtual, it is not a good practice to change methods on your classes to virtual to allow them to be unit tested. Methods should be declared as virtual if you wish for them to be overridable by inheriting classes. If you find yourself declaring a good amount of your methods as virtual on classes for the sake of unit testing, that’s a sign you should step back and take a look at your design. Can or should you be using an interface to represent the contract of the class you’re currently using and implement the functionality that used to be in your class in the interface implementation? As usual, there is no hard and fast rule for this, but be on the lookout for this type of code creeping into your codebase.

Summary

In this chapter, we’ve covered the higher level “rules” that govern how FakeItEasy can work, and looked at example code that illustrates how to use it, and how not to use it. Next, we’ll start learning to use FakeItEasy by learning how to create fakes.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.