DataverseFakes.Community
1.1.5
dotnet add package DataverseFakes.Community --version 1.1.5
NuGet\Install-Package DataverseFakes.Community -Version 1.1.5
<PackageReference Include="DataverseFakes.Community" Version="1.1.5" />
<PackageVersion Include="DataverseFakes.Community" Version="1.1.5" />
<PackageReference Include="DataverseFakes.Community" />
paket add DataverseFakes.Community --version 1.1.5
#r "nuget: DataverseFakes.Community, 1.1.5"
#:package DataverseFakes.Community@1.1.5
#addin nuget:?package=DataverseFakes.Community&version=1.1.5
#tool nuget:?package=DataverseFakes.Community&version=1.1.5
DataverseFakes
A modern, open-source unit testing framework for Dynamics 365 / Dataverse that mocks IOrganizationService with an in-memory context for fast plugin, workflow, and custom code testing.
Features
- Unit test plugins without deploying to a real environment
- Test workflow activities with in-memory execution
- Fast execution - run 1000+ tests in seconds
- No server required - test offline, no Dynamics 365 connection needed
- Early and late bound - works with generated entities or dynamic
Entityobjects - 62+ SDK messages supported out of the box
- Pipeline simulation - register plugin steps with filtering attributes, stages, and rank ordering
- FetchXML and QueryExpression - full query translation with aggregates, joins, and date operators
Getting Started
Installation
dotnet add package DataverseFakes.Community
Or via Package Manager:
Install-Package DataverseFakes.Community
Quick Example
using DataverseFakes;
using Microsoft.Xrm.Sdk;
using Xunit;
public class AccountPluginTests
{
[Fact]
public void When_Account_Created_Should_Set_AccountNumber()
{
// Arrange
var context = new XrmFakedContext();
var target = new Entity("account")
{
["name"] = "Contoso"
};
// Act
context.ExecutePluginWithTarget<AccountNumberPlugin>(target);
// Assert
Assert.True(target.Contains("accountnumber"));
Assert.NotNull(target["accountnumber"]);
}
}
Early-Bound Entities
var context = new XrmFakedContext();
context.ProxyTypesAssembly = Assembly.GetExecutingAssembly();
var account = new Account
{
Id = Guid.NewGuid(),
Name = "Test Account"
};
context.Initialize(new List<Entity> { account });
var service = context.GetOrganizationService();
Testing Workflow Activities
var context = new XrmFakedContext();
var inputs = new Dictionary<string, object>
{
{ "Target", new EntityReference("account", Guid.NewGuid()) },
{ "InputText", "Hello" }
};
var outputs = context.ExecuteCodeActivity<MyCustomActivity>(inputs);
Assert.Equal("Hello World", outputs["OutputText"]);
Plugin Pipeline Simulation
var context = new XrmFakedContext();
context.UsePipelineSimulation = true;
// Register plugin steps with filtering attributes
context.RegisterPluginStep<AccountPlugin, Account>(
message: "Create",
stage: ProcessingStepStage.Preoperation,
mode: ProcessingStepMode.Synchronous,
rank: 1,
filteringAttributes: new[] { "name", "revenue" }
);
// Entity images auto-populated from context
context.ExecutePluginWithTarget<MyPlugin>(target,
messageName: "Update",
stage: 40,
preImageColumns: new ColumnSet(true),
postImageColumns: new ColumnSet(true));
Supported SDK Messages
DataverseFakes supports 62+ standard CRM messages:
| Category | Messages |
|---|---|
| CRUD | Create, Retrieve, Update, Delete, Upsert, RetrieveMultiple |
| Bulk | CreateMultiple, UpdateMultiple, DeleteMultiple, UpsertMultiple, ExecuteMultiple, ExecuteTransaction, BulkDelete |
| Async | ExecuteAsync (with AsyncOperation tracking) |
| Relationships | Associate, Disassociate, Assign (with alternate key support) |
| Security | GrantAccess, RevokeAccess, ModifyAccess, RetrievePrincipalAccess, AddUserToRecordTeam |
| Teams | AddMembersTeam, RemoveMembersTeam |
| Queues | AddToQueue, PickFromQueue, RemoveFromQueue |
| Sales | QualifyLead, WinOpportunity, LoseOpportunity, CloseQuote, WinQuote, ReviseQuote, CloseIncident |
| Metadata | CreateEntity, UpdateEntity, DeleteEntity, RetrieveEntity, RetrieveAttribute, RetrieveRelationship, RetrieveMetadataChanges, CRUD OptionSets |
| Utility | WhoAmI, RetrieveVersion, CalculateRollupField, InitializeFrom, FetchXmlToQueryExpression, SendEmail, PublishXml |
Query Support
Result Ordering
DataverseFakes matches Dataverse behavior: result ordering is not guaranteed unless you explicitly specify an OrderExpression or <order /> clause. Use set/membership assertions instead of index-based assertions:
var results = service.RetrieveMultiple(query);
var ids = results.Entities.Select(e => e.Id).ToList();
Assert.Contains(expectedId, ids);
Condition Operators
| Category | Operators |
|---|---|
| Comparison | Equal, NotEqual, GreaterThan, GreaterEqual, LessThan, LessEqual |
| Null | Null, NotNull |
| String | Like (with %, _, [A-Z], [abc], [^abc]), NotLike, BeginsWith, EndsWith, Contains |
| Set | In, NotIn, Between, NotBetween, ContainValues, DoesNotContainValues |
| User/Business | EqualUserId, NotEqualUserId, EqualBusinessId, NotEqualBusinessId |
| Date | Today, Yesterday, Tomorrow, Last7Days, LastXDays, NextXDays, ThisWeek, ThisMonth, ThisYear, and many more |
| Fiscal | InFiscalYear, InFiscalPeriod, ThisFiscalPeriod, LastFiscalPeriod, NextFiscalPeriod |
| Any/All | JoinOperator.Any, NotAny, All, NotAll (subquery-style filters) |
FetchXML Aggregates
var fetchXml = @"<fetch aggregate='true'>
<entity name='contact'>
<attribute name='contactid' alias='count' aggregate='count' />
<attribute name='lastname' alias='group' groupby='true' />
</entity>
</fetch>";
var results = service.RetrieveMultiple(new FetchExpression(fetchXml));
Alternate Keys
// Define alternate keys
context.AddAlternateKey("account", "accountnumber", "Account Number Key");
context.AddAlternateKey("product", new[] { "productnumber", "productcategoryid" }, "Composite Key");
// Retrieve by alternate key
var entity = new Entity("account");
entity.KeyAttributes["accountnumber"] = "ACC-001";
var result = service.Retrieve("account", entity.KeyAttributes, new ColumnSet(true));
// Upsert by alternate key
var upsert = new Entity("account");
upsert.KeyAttributes["accountnumber"] = "ACC-002";
upsert["name"] = "New or Updated";
service.Execute(new UpsertRequest { Target = upsert });
Known Limitations
| Limitation | Description |
|---|---|
| Complex Aggregations | Some complex FetchXML aggregations may not match Dataverse behavior exactly |
| Calculated Fields | Require manual setup via CalculateRollupFieldRequest |
| Business Rules | Client-side business rules are not simulated |
| Real-time Workflows | Workflows and flows are not automatically triggered |
| File/Image Attributes | Limited support for file and image column types |
Building from Source
build.bat # Restore, build, and test
build.bat test # Run tests only
build.bat pack # Create NuGet package
Target Platform: Dynamics 365 v9.x and later (.NET Framework 4.6.2)
Contributing
- Fork the repository
- Create a feature branch
- Write tests for your changes
- Open a Pull Request
All new features and bug fixes must include unit tests.
License
MIT License - see LICENSE.md for details.
Attribution
This project is derived from FakeXrmEasy, originally created by Jordi Montana and contributors.
FakeXrmEasy is a registered trademark of Jordi Montana. This project is not affiliated with or endorsed by the trademark holder.
See CHANGELOG.md for version history.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET Framework | net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
-
.NETFramework 4.6.2
- FakeItEasy (>= 6.0.0)
- Microsoft.CrmSdk.CoreAssemblies (>= 9.0.2.60)
- Microsoft.CrmSdk.Deployment (>= 9.0.2.34)
- Microsoft.CrmSdk.Workflow (>= 9.0.2.60)
- Microsoft.CrmSdk.XrmTooling.CoreAssembly (>= 9.1.1.65)
- Newtonsoft.Json (>= 13.0.4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.5 | 153 | 4/8/2026 |