C# FakeItEasy
last modified September 2, 2023
In this article we show how to do mocking in C# using the FakeItEasy library.
Faking is replacing external dependencies with fakes or test doubles. These classes or components simulate successful or failed operations in unit testing.
Fakes are used primarily because the external dependencies might currently not be available for testing or their usage is very costly.
FakeItEasy is an easy mocking library for .NET.
$ dotnet add package FakeItEasy $ dotnet add package Microsoft.NET.Test.Sdk $ dotnet add package MSTest.TestAdapter $ dotnet add package MSTest.TestFramework
In this article we use the MSTest testing framework.
C# FakeItEasy simple example
In the first example, we replace a simple HelloService
class with
a fake.
namespace Messages.Services; public interface IMessageService { string GetHelloMessage(); string GetGreetingMessage(); }
FakeItEasy creates fakes from the IMessageService
interface.
namespace Messages.Services; public class MessageService : IMessageService { public string GetHelloMessage() { return "Hello there!"; } public string GetGreetingMessage() { return "Good Morning!"; } }
MessageService
is the implementation of the
IMessageService
.
namespace Messages.Tests; using Microsoft.VisualStudio.TestTools.UnitTesting; using FakeItEasy; using Messages.Services; [TestClass] public class MessageServiceTest { private const string Expected1 = "Hello there!"; private const string Expected2 = "Good Morning!"; [TestMethod] public void HelloMessageTest() { var msgService = A.Fake<IMessageService>(); A.CallTo(() => msgService.GetHelloMessage()).Returns(Expected1); var res = msgService.GetHelloMessage(); Assert.AreEqual(Expected1, res); } [TestMethod] public void GreetingMessageTest() { var msgService = A.Fake<IMessageService>(); A.CallTo(() => msgService.GetGreetingMessage()).Returns(Expected2); var res = msgService.GetGreetingMessage(); Assert.AreEqual(Expected2, res); } }
In MessageServiceTest
, we test the MessageService
class.
var msgService = A.Fake<IMessageService>(); A.CallTo(() => msgService.GetHelloMessage()).Returns(Expected1);
We create a fake MessageService
from the
IMessageService
interface and define a response for the
GetHelloMessage
call.
var res = msgService.GetHelloMessage(); Assert.AreEqual(Expected1, res);
The method is tested using a fake not a real class.
C# FakeItEasy example II
Since we have a console program with a testing framework, we need to add the following option to the project file.
<GenerateProgramFile>false</GenerateProgramFile>
Otherwise, we have two main entry points clashing.
$ dotnet add package Bogus
In addition to the previously mentioned packages, we also add the Bogus library to create fake data.
namespace Users.Models; public class User { public User(string fname, string lname, string occupation) => (FirstName, LastName, Occupation) = (fname, lname, occupation); public string FirstName { get; set; } public string LastName { get; set; } public string Occupation { get; set; } public override string ToString() => $"{FirstName} {LastName} is a {Occupation}"; }
This is the User
class.
namespace Users.Services; using Users.Models; public interface IUserService { User GetUser(); IList<User> GetUsers(int n); }
We have an IUserService
interface with two contract methods.
The GetUser
returns a single user and the GetUsers
returns the n number of users.
namespace Users.Services; using Users.Models; using Bogus; public class UserService : IUserService { private List<string> occupations = new List<string> { "teacher", "programmer", "driver", "accountant" }; public IList<User> GetUsers(int n) { var users = new List<User>(); foreach (int value in Enumerable.Range(1, n)) { users.Add(CreateUser()); } return users; } public User GetUser() { var user = CreateUser(); return user; } public User CreateUser() { var faker = new Faker(); var fname = faker.Person.FirstName; var lname = faker.Person.LastName; int n = occupations.Count(); int millis = DateTime.Now.Millisecond; var occupation = occupations.ElementAt(new Random(millis).Next(n)); return new User(fname, lname, occupation); } }
Our UserService
implements the contract methods. It uses Bogus
to generate fake data for the users.
namespace Main; using Users.Services; public class Program { public static void Main(string[] args) { var userService = new UserService(); var u1 = userService.GetUser(); Console.WriteLine(u1); var users = userService.GetUsers(5); Console.WriteLine(string.Join("\n", users)); } }
This is the main console program that uses the userService
.
namespace UserService.Tests; using Microsoft.VisualStudio.TestTools.UnitTesting; using FakeItEasy; using Users.Services; using Users.Models; [TestClass] public class MessageTest { [TestMethod] public void GetUserTest() { var userService = A.Fake<IUserService>(); var dummyUser = A.Dummy<User>(); A.CallTo(() => userService.GetUser()).Returns(dummyUser); var res = userService.GetUser(); Assert.AreEqual(dummyUser, res); } [TestMethod] [DataRow(2)] [DataRow(5)] [DataRow(10)] public void GetUsersTest(int n) { var userService = A.Fake<IUserService>(); var dummyUsers = A.CollectionOfFake<User>(n); A.CallTo(() => userService.GetUsers(n)).Returns(dummyUsers); var res = userService.GetUsers(n); Assert.AreEqual(dummyUsers, res); } }
We test the UserService
class with a test double.
var userService = A.Fake<IUserService>();
First, we create a fake UserService
.
var dummyUser = A.Dummy<User>(); A.CallTo(() => userService.GetUser()).Returns(dummyUser);
Then we define a dummy user and set it as a response for the
GetUser
method call.
var res = userService.GetUser(); Assert.AreEqual(dummyUser, res);
Finally, we test the GetUser
method using the test double.
[TestMethod] [DataRow(2)] [DataRow(5)] [DataRow(10)] public void GetUsersTest(int n) { var userService = A.Fake<IUserService>(); var dummyUsers = A.CollectionOfFake<User>(n); A.CallTo(() => userService.GetUsers(n)).Returns(dummyUsers); var res = userService.GetUsers(n); Assert.AreEqual(dummyUsers, res); }
With MSTest's DataRow
, we run the GetUsers
method
with values 2, 5, and 10 consecutively.
Source
In this article we have replaced two real classes with test doubles in C# with FakeItEasy.
Author
List all C# tutorials.