如何使用 ServiceFabric.Mocks Nuget 包模拟配置和数据包的 CodePackageActivationContext
How do you Mock CodePackageActivationContext for Config and Data Package using ServiceFabric.Mocks Nuget package
这是
的后续问题
我正在使用 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");" returns 对“dataPackage”为空。因此对 IsDataJsonLoaded returns 'False'.
的断言
我在 Whosebug 上四处搜索,发现这个答案最能回答我的问题: 但是在使用这个答案中的代码时,我的单元测试看起来像这样:
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;” context 和单独的“MockStatelessServiceContextFactory.Default”上下文传递给单元测试中 SearchServiceClass 的构造函数,CodePackageActivation 在 Mock StatelessServiceContext 中不存在。不确定这是否有意义......但本质上,这似乎导致构造函数中 dataPackage.Path 引用中的“NullReferenceException”。有什么解决办法吗?
你走对了!
- 第 1 步
类 ConfigurationSection
和 ConfigurationProperty
在 SF 命名空间 System.Fabric.Description
中。为命名空间
添加一个using
- 第 2 步
请升级到 ServiceFabric.Mocks v4.2.8。这增加了对 MockCodePackageActivationContext
上模拟 DataPackage
属性 的支持。
有关示例,请参阅 this page。
- 步骤 3.
使用创建的上下文作为构造函数参数。
更改此代码:
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);
这是
我正在使用 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");" returns 对“dataPackage”为空。因此对 IsDataJsonLoaded returns 'False'.
的断言我在 Whosebug 上四处搜索,发现这个答案最能回答我的问题:
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;” context 和单独的“MockStatelessServiceContextFactory.Default”上下文传递给单元测试中 SearchServiceClass 的构造函数,CodePackageActivation 在 Mock StatelessServiceContext 中不存在。不确定这是否有意义......但本质上,这似乎导致构造函数中 dataPackage.Path 引用中的“NullReferenceException”。有什么解决办法吗?
你走对了!
- 第 1 步
类 ConfigurationSection
和 ConfigurationProperty
在 SF 命名空间 System.Fabric.Description
中。为命名空间
using
- 第 2 步
请升级到 ServiceFabric.Mocks v4.2.8。这增加了对 MockCodePackageActivationContext
上模拟 DataPackage
属性 的支持。
有关示例,请参阅 this page。
- 步骤 3.
使用创建的上下文作为构造函数参数。 更改此代码:
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);