MakeItEasy: Making SUTs with Minimal Fuss

Recently a FakeItEasy user came to our Gitter channel asking about easier ways to create their systems under test and the Fakes that those systems depend on. They referenced the old UnderTest and Fake attributes that FakeItEasy used to provide for this purpose, but which had been removed when FakeItEasy 5.0.0 was released.

There are some existing libraries that provide this functionality, or something like it, such as

but I thought there was room for improvement. The first two pull along additional libraries with them, either for complete test data generation or for generalized dependency injection. This isn't a problem (and may be a feature) if you're already using those libraries, but could be overwhelming if you're not. FakeItEasy.Auto has a nice light interface, but appears to be abandoned and only supports .NET Framework 4.5.

So my FakeItEasy co-conspirator Thomas Levesque and I chatted about how to design a simple interface to create the system under test. We (or if I'm being honest, mostly he) arrived at an API that

  1. doesn't require the user to specify any arguments that they don't care about
  2. doesn't require fields or properties on the test fixture, or use of any attributes
  3. allows users to provide any values to the SUT's constructor
  4. makes it easy to retrieve (and later configure) Faked collaborators
MakeItEasy Logo

Creating a System Under Test using MakeItEasy

MakeItEasy is an attempt to fulfill the requirements laid out above. The Make class is its single entry point and allows you to create your system under test:

import MakeItEasy;

// ...

var systemUnderTest = Make.A<VeryNeedySystem>().FromDefaults();
The simplest way to create your system under test

That's it. If VeryNeedySystem has a public constructor whose arguments can be made from FakeItEasy Dummies, MakeItEasy will make it for you. It doesn't matter if the constructor has 1 parameter or 14.

Making and Using Fake collaborators

The example above looks great, but more often you'll want to access the Fake object(s) that the SUT will be using. Then you can configure them, or maybe interrogate them after the system under test has been exercised. This is also very easy:

var systemUnderTest = Make.A<VeryNeedySystem>().From(
    out ICollaborator fakeCollaborator);

// A.CallTo(() => fakeCollaborator.SomeMethod()).Returns(1);
// exercise systemUnderTest
// A.CallTo(() => fakeCollaborator.SomeMethod()).MustHaveHappened();
Create a system under test and access a Fake collaborator

Currently MakeItEasy supports up to 8 out parameters, which will be populated with Fakes and passed as constructor arguments to the system under test.

You can even call Make from a setup method and initialize fields, if you prefer not to use local variables for the collaborators.

Supplying Arbitrary Constructor arguments

Maybe the system under test's constructor requires some non-Fake additional parameters. MakeItEasy will usually populate these with Dummies, but if you have a particular value you want to supply, you can do that:

var systemUnderTest = Make.A<VeryNeedySystem>().From(
    DateTime.Now);
Create a system under test using supplied arguments

You can supply up to 8 constructor arguments.

"Advanced" Usage

You can request Fake collaborators and supply arguments at the same time, of course.

var systemUnderTest = Make.A<VeryNeedySystem>().From(
    DateTime.Now,
    out ICollaborator fakeCollaborator);
Create a system under test specifying an argument and accessing a Fake collaborator

As before, you can supply up to 8 arguments and request up to 8 collaborators back.

MakeItEasy doesn't provide a way to customize the Fake before it's passed to the constructor of the system under test. If you need this behaviour, you can always create the Fake "by hand", configure it, and then pass it in. Or maybe you want to share a Fake between systems under test. All this is supported, even in combination.

var oneSystemUnderTest = Make.A<VeryNeedySystem>().From(
    out ICollaborator fakeCollaborator);

// configure the fakeCollaborator somehow

var anotherSystemUnderTest = Make.An<OtherKindOfSystem>().From(
    fakeCollaborator);
Share Fakes between classes under test

What Next?

If you're interested in trying MakeItEasy, get the latest release from NuGet. Tell me what you think. What works for you? What doesn't? Chat here or raise an issue.

~ ~

Why I Teach Git Using Only the Command Line

At the Day Job, we're about to transition something like 150 Subversion repos to a single git monorepo. Part of my contribution will be training several tens of git-unaware developers in my office on the basics of working with git.

I was chatting about training approaches with my counterpart in …

~ ~

LibraryHippo 2020 - Recap and decision

In each of last six articles I've satisfied one of the high-risk requirements I had for moving LibraryHippo to the Flask framework, with the goal of hosting it on Heroku. This leaves three "softer" requirements open, which I'll address here.

(Aside: It feels a little weird working on this conversion …

~ ~

LibraryHippo 2020 - Social Login

I now have a functioning skeleton of a shadow LibraryHippo site. The last gaping hole is that it treats every visitor the same. We need to be able to distinguish one user from the next and to retain information about them between visits, such as which family they belong to …

~ ~

LibraryHippo 2020 - A Bare-bones Flask App

Last time I laid out the uncertainties that have to be explore before I want to try hosting LibraryHippo on Heroku. Here they are again, roughly in descending order of importance and risk:

  1. web app hosting
  2. scheduled jobs
  3. scraping library websites on users' behalf
  4. a small (perhaps a few MB …

~ ~

Automatically Sync nupkg and project.json Dependencies

Recently while working on an open source .NET project, I forgot to update the .nuspec after changing a package dependency in my project.json. Of course the resulting nupkg contained the wrong dependency. Fortunately, the package wasn't published in that state, but I didn't want to risk such a thing …

~ ~

page 1 | older articles »