There is a fundamental principle in FakeXrmEasy: which is that is designed as a data-driven test driven development framework.
FakeXrmEasy abstracts the implementation of the IOrganizationService, IOrganizationServiceAsync and IOrganizationServiceAsync2 interfaces.
This saves you from not having to mock requests that implement those interfaces.
FakeXrmEasy simulates a Dataverse backend by keeping an In-Memory database that stores the data in Entities (or Tables) as well as the metadata of these Entities (or Tables).
FakeXrmEasy also comes with a query translation engine that will execute your FetchXml, QueryExpress, QueryByAttribute or CRM LINQ provider queries against such In-memory database. Meaning you could even also test these queries!
Traditional approach with TDD frameworks was to mock interfaces to return dummy responses for purposes of testing functionality.
With FakeXrmEasy, instead, you would setup some minimum data in-memory (if needed) for your logic to be executed, and then, query the state of the In-Memory database after the execution.
From the point of view of the test runner, it’s also an unopinionated mocking framework: you can choose your test runner of choice (xUnit, MSTest, NUnit, etc). The samples below will use xUnit though.
Here’s an example of a unit test that verifies a contact is updated in Dataverse (in this example, _context and _service variables have already been defined in the base test class using a middleware builder: FakeXrmEasyTestsBase (please do check the Middleware documentation for more details))
public class ContactTests : FakeXrmEasyTestsBase
{
private readonly Contact _contact;
public ContactTests()
{
_contact = new Contact() { Id = Guid.NewGuid(), FirstName = "Pepe" };
}
[Fact]
public void Should_update_an_existing_contact()
{
//The In-Memory database is initialised with just one contact with name "Pepe"
_context.Initialize(_contact);
//Execute the system under test
var cmd = new UpdateContactCommand(_service);
cmd.ContactId = _contact.Id;
cmd.FirstName = "Jose";
cmd.Execute();
//Retrieve state of the In-Memory database after execution
var contactUpdated = _context.CreateQuery<Contact>().FirstOrDefault();
//We, then, verify that the contact was updated with the new name
Assert.Equal("Jose", contactUpdated.FirstName);
}
}
And here’s the code that implements the logic that the unit test above verifies. Note, in order to properly test your code, the code should only reference IOrganizationService, IOrganizationServiceAsync or IOrganizationServiceAsync2 interfaces.
public class UpdateContactCommand
{
public Guid ContactId { get; set; }
public string FirstName { get; set; }
private readonly IOrganizationService _service;
public UpdateContactCommand(IOrganizationService service)
{
_service = service;
}
public void Execute()
{
_service.Update(new Contact() {
Id = ContactId,
FirstName = FirstName
});
}
}
As you can see, no mocks were needed, FakeXrmEasy implements those internally and it gives you an IOrganizationService interface that is ready to use.