如何在FakeXrmEasy单元测试中模拟Dynamics 365货币字段本位币重算?
解决FakeXrmEasy中货币字段本位币自动重算的问题
我之前在FakeXrmEasy里测试Dynamics 365货币字段的时候,也碰到过一模一样的问题——系统自动生成的_Base本位币字段不会自动计算,导致求和结果不符合预期。下面给你分享几个实用的解决思路:
1. 简单场景:手动设置本位币字段
如果你的测试场景比较简单(比如固定汇率、不需要模拟复杂的货币转换逻辑),最直接的办法就是在设置普通货币字段的同时,手动给_Base字段赋值:
// 设置业务货币字段 localAccount.turnover = new Money(100); // 根据测试场景的汇率手动设置本位币字段(这里假设汇率是1:1) localAccount.turnover_Base = new Money(100);
这种方式快速高效,适合只需要验证求和逻辑本身,不需要模拟系统货币转换流程的测试用例。
2. 贴近实际:模拟系统货币重算插件
在Dynamics 365实际环境中,本位币字段的计算是由系统内置插件完成的——它会根据实体的货币类型(currencyid)和汇率表中的汇率,自动转换并填充_Base字段。我们可以在FakeXrmEasy中注册一个模拟插件,还原这个逻辑:
第一步:编写模拟转换插件
public class CurrencyConversionSimulatorPlugin : IPlugin { public void Execute(IServiceProvider serviceProvider) { var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); var targetEntity = context.InputParameters["Target"] as Entity; // 只处理Account实体的turnover字段更新/创建 if (targetEntity?.LogicalName != "account" || !targetEntity.Contains("turnover")) return; // 获取业务货币值 var transactionCurrencyValue = (Money)targetEntity["turnover"]; // 模拟汇率获取逻辑:可以固定值,也可以从测试数据中查询Currency实体的汇率 // 这里我们用固定汇率1.2来举例 decimal exchangeRate = 1.2m; // 计算并设置本位币字段 targetEntity["turnover_Base"] = new Money(transactionCurrencyValue.Value * exchangeRate); } }
第二步:在测试中注册插件
在你的测试初始化代码里,把这个插件注册到对应的实体和操作上:
// 初始化FakeXrmEasy上下文 var fakedContext = new XrmFakedContext(); // 注册插件,模拟系统在PreOperation阶段处理Create和Update操作时的货币转换 fakedContext.RegisterPluginStep<CurrencyConversionSimulatorPlugin>( entityLogicalName: "account", stage: PluginStage.PreOperation, messageName: MessageName.Create, messageName: MessageName.Update ); // 创建测试账户 var testAccount = new Account { Name = "Test Account", turnover = new Money(100) }; fakedContext.Create(testAccount); // 现在查询并求和,就能得到正确的本位币值(100*1.2=120) var allAccounts = fakedContext.CreateQuery<Account>().ToList(); var sumOfTurnovers = allAccounts.Sum(s => s.turnover_Base?.Value ?? 0); // sumOfTurnovers的值应该是120
这种方式的好处是完全模拟了Dynamics 365的实际运行逻辑,测试结果更贴近生产环境,适合需要验证复杂业务流程的场景。
3. 进阶优化:动态获取测试汇率
如果你的测试需要模拟不同的货币类型和汇率,可以在测试数据中预先创建currency实体,然后在插件中通过组织服务查询对应的汇率:
// 在插件中获取组织服务 var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); var service = serviceFactory.CreateOrganizationService(context.UserId); // 获取当前账户的货币类型ID var currencyId = targetEntity.GetAttributeValue<Guid>("currencyid"); // 查询对应的Currency实体获取汇率 var currency = service.Retrieve("currency", currencyId, new ColumnSet("exchangerate")); decimal exchangeRate = currency.GetAttributeValue<decimal>("exchangerate");
这样就能根据测试中设置的不同货币,动态计算本位币值,让测试更灵活。
内容的提问来源于stack exchange,提问作者A.D.
相关产品推荐
相关产品推荐

