The FakeXrmEasy framework has become the actual standard for mocking the Dataverse context for our code unit testing. Thanks to it, we do not have any problems with providing in-memory data for our tests instead of using the real Dataverse service. But what about metadata? Is there any way of easily providing mocked information about our tables and other Dataverse components?
Let’s take a quick look at the following example.
A few days ago, I wrote some code retrieving entity meta using the Dataverse table’s name. As you can see below, it is a very simple method consumed by other methods that were tested.
public virtual EntityMetadata RetrieveEntityMetadata(bool retrieveAsIfPublished, string logicalName)
{
return ((RetrieveEntityResponse)this.service.Execute(new RetrieveEntityRequest
{
RetrieveAsIfPublished = retrieveAsIfPublished,
EntityFilters = EntityFilters.All,
LogicalName = logicalName
})).EntityMetadata;
}
During test execution, I was getting the following error:
FakeXrmEasy.Abstractions.Exceptions.OpenSourceUnsupportedException : Exception occurred: The organization request type 'Microsoft.Xrm.Sdk.Messages.RetrieveEntityRequest' is not yet supported...
Ok. The error message is not exactly true because there is an easy way to get rid of this exception. The only thing we need to do is add the FakeXrmEasy.Messages.v9 NuGet package to our project and use the AddFakeMessageExecutors
method during context initialization with MiddlewareBuilder
.
var context = MiddlewareBuilder
.New()
.AddCrud()
.AddFakeMessageExecutors(Assembly.GetAssembly(typeof(AddListMembersListRequestExecutor)))
.UseCrud()
.UseMessages()
.SetLicense(FakeXrmEasyLicense.RPL_1_5)
.Build();
The next step is to add the following line to our test code:
var metadata = new EntityMetadata(){ LogicalName = Account.EntityLogicalName };
context.InitializeMetadata(metadata);
The next problem I’ve met was about setting EntityMetadata
object properties to simulate some business logic with them. However, most of its properties are read-only. It makes sense when using it in a real environment, but it brings some trouble when testing code using it. Fortunately, another technique makes setting its properties possible. Ladies and gentlemen, here comes the reflection!
var metadata = new EntityMetadata() { LogicalName = Account.EntityLogicalName };
metadata.GetType()?.GetProperty(nameof(metadata.ObjectTypeCode))?.SetValue(metadata, 1);
The above code sets the ObjectTypeCode
property of the metadata object with a numeric value. Yes, I’m aware that reflection is not the nicest thing that should be used inside unit testing, but let’s be practical and use solutions that could help us solve our problems instead of introducing additional abstraction layers above the Microsoft-provided SDK.
Keep it simple!