如何使用 ServiceFabric.Mocks Nuget 包模拟配置和数据包的 CodePackageActivationContext
Posted
技术标签:
【中文标题】如何使用 ServiceFabric.Mocks Nuget 包模拟配置和数据包的 CodePackageActivationContext【英文标题】:How do you Mock CodePackageActivationContext for Config and Data Package using ServiceFabric.Mocks Nuget package 【发布时间】:2021-03-28 16:12:34 【问题描述】:这是Specific questions about unit-testing Service Fabric Applications using Mocks的后续问题
我正在使用 Xunit 和 ServiceFabric.Mocks 对我的应用程序进行单元测试。 我的 Service Fabric 应用程序如下所示:
namespace SearchService
internal sealed class SearchServiceClass : StatelessService
//variables defined followed by constructor
private string jsonStr;
public SearchServiceClass(StatelessServiceContext context)
: base(context)
try
var section = Context.CodePackageActivationContext
.GetConfigurationPackageObject("Config")
.Settings
.Sections[_configSectionName];
var _parameters = section.Parameters.ToDictionary(kv => kv.Name, kv => kv.Value);
//_parameters used to set further variables in the constructor
var dataPackage = Context.CodePackageActivationContext
.GetDataPackageObject("Data");
jsonStr = File.ReadAllText(dataPackage.Path + @"\data.json");
//removed code for brevity
catch
//exception handling code
throw;
public bool IsDataJsonLoaded
get
return !(jsonStr == null);
初始单元测试如下所示:
using Xunit;
using ServiceFabric.Mocks;
namespace App.UnitTests
public class SearchServiceTest
[Fact]
public void SearchServiceClassConstructor()
var searchServiceClass = new SearchServiceClass(MockStatelessServiceContextFactory.Default);
//assert:
Assert.True(searchServiceClass.IsDataJsonLoaded);
当我运行此单元测试时,“System.NullReferenceException:对象引用未设置为对象的实例。”抛出异常。这是因为在单元测试设置中,“Context.CodePackageActivationContext.GetDataPackageObject("Data");"将 null 返回到“dataPackage”。因此 IsDataJsonLoaded 上的断言返回 'False'。
我在 *** 上四处搜索,发现这个答案最能回答我的问题:https://***.com/a/57803921/14761454 但是在使用这个答案中的代码时,我的单元测试看起来像这样:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ServiceFabric.Mocks;
using SearchService;
using Xunit;
using static ServiceFabric.Mocks.MockConfigurationPackage;
namespace App.UnitTests
public class SearchServiceTest
[Fact]
public void SearchServiceClassConstructor()
//Arrange
const string path = "../SearchService/PackageRoot/Data"; //The Data Package lives in the SearchService project, specifically PackageRoot/Data
const string name = "Data";
const string version = "1.0.0";
const string serviceManifestName = "SearchServicePkg";
const string serviceManifestVersion = "1.0.0";
var dataPackageDescription = MockDataPackage.CreateDataPackageDescription(name, version, serviceManifestName, serviceManifestVersion, path);
var dataPackage = MockDataPackage.CreateDataPackage(path, dataPackageDescription);
//build ConfigurationSectionCollection
var configSections = new ConfigurationSectionCollection();
//Build ConfigurationSettings
var configSettings = CreateConfigurationSettings(configSections);
//add one ConfigurationSection
ConfigurationSection configSection = CreateConfigurationSection("SearchServiceConfigSection");
configSections.Add(configSection);
//add one Parameters entry
ConfigurationProperty parameter = CreateConfigurationSectionParameters(nameof(parameter.Name), nameof(parameter.Value));
configSection.Parameters.Add(parameter);
var Context = MockCodePackageActivationContext.Default;
var searchServiceClass = new SearchServiceClass(MockStatelessServiceContextFactory.Default);
//Act
Context.SetDataPackage(dataPackage);
//Assert:
Assert.True(searchServiceClass.IsDataJsonLoaded);
但是现在编译器会抛出错误,说在命名空间中找不到“ConfigurationSection”和“ConfigurationProperty”。
我在正确的轨道上吗?如果我这样继续,我是否完全能够从单元测试环境中的实际 StatelessService 模拟配置和数据包。如何先修复这些错误?
编辑:根据下面 LoekD 的响应,我已更新到 ServiceFabric.Mocks v4.2.8,并实现了附加代码来模拟数据包。但是 NullReferenceException 仍然存在。此错误对应于 SearchServiceClass 的构造函数中的“dataPackage.Path”行。虽然现在有一个单独的“MockCodePackageActivationContext.Default;”上下文和一个单独的“MockStatelessServiceContextFactory.Default”上下文在单元测试中传递给 SearchServiceClass 的构造函数,在 Mock StatelessServiceContext 中不存在 CodePackageActivation。不确定这是否有意义......但本质上,这似乎导致了构造函数中 dataPackage.Path 引用中的“NullReferenceException”。任何想法如何解决这个问题?
【问题讨论】:
尝试使用:csharpdoc.hotexamples.com/class/Iot.Mocks/… 【参考方案1】:你在正确的轨道上!
第 1 步。ConfigurationSection
和 ConfigurationProperty
类位于 SF 命名空间 System.Fabric.Description
中。为命名空间添加using
请升级到 ServiceFabric.Mocks v4.2.8。这增加了对模拟MockCodePackageActivationContext
上的DataPackage
属性的支持。
示例见this page。
使用创建的上下文作为构造函数参数。 更改此代码:
var searchServiceClass = new SearchServiceClass(MockStatelessServiceContextFactory.Default);
进入这个:
var activationContext = new MockCodePackageActivationContext(
"fabric:/MockApp",
"MockAppType",
"Code",
"1.0.0.0",
Guid.NewGuid().ToString(),
@"C:\logDirectory",
@"C:\tempDirectory",
@"C:\workDirectory",
"ServiceManifestName",
"1.0.0.0")
ConfigurationPackage = configPackage
;
activationContext.SetDataPackage(dataPackage);
var newUri = new Uri("fabric:/MockApp/SearchService");
var serviceTypeName = "SearchServiceType";
var partitionId = Guid.NewGuid();
var replicaId = long.MaxValue;
var serviceContext = MockStatelessServiceContextFactory.Create(activationContext, serviceTypeName, newUri, partitionId, replicaId);
var searchServiceClass = new SearchServiceClass(serviceContext);
【讨论】:
非常感谢。我首先修复了命名空间问题。然后我看到了模拟“DataPackage”的代码,在我的单元测试中实现了相同的。我没有得到的是如何修复我在运行单元测试时得到的“NullReferenceException”。此错误对应于 SearchServiceClass 的构造函数中的“dataPackage.Path”行。虽然现在有一个单独的“MockCodePackageActivationContext.Default;”在单元测试中将上下文和单独的“MockStatelessServiceContextFactory.Default”上下文传递给 SearchServiceClass 的构造函数,CodePackageActivation 不存在.. ..(续)在 Mock StatelessServiceContext 中。不确定这是否有意义......但本质上,这似乎导致了构造函数中 dataPackage.Path 引用中的“NullReferenceException”。任何想法如何解决这个问题? 我已经更新了我的问题。您能否看一下,让我知道我试图在构造函数中模拟的代码是否真的可以被模拟? 代替Default
实例,使用您自己定制的Context
实例作为构造函数参数(见上文)。
对不起,我混淆了服务上下文和代码包激活上下文,更改了我的代码。以上是关于如何使用 ServiceFabric.Mocks Nuget 包模拟配置和数据包的 CodePackageActivationContext的主要内容,如果未能解决你的问题,请参考以下文章
如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]