配置.单元测试中的管理器
本文关键字:管理器 单元测试 配置 | 更新日期: 2023-09-27 18:14:17
我已经读了一些关于这个问题的很好的问题和答案例如不能在单元测试项目中使用ConfigurationManager
和如何模拟ConfigurationManager。AppSettings with moq
目前,我在单元测试中使用的解决方案是为单元测试项目建议一个App.config文件。它工作得很好。
我的目标是动态加载插件(*.dll)到我的c#项目。
这里是我的原始App.config
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicFormattedKeyToken=b77a5c561934e089">
<section name="IQCMain.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicFormattedKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
<section name="CalibrationToolsSection" type="sec.Calibration.Configuration.CalibrationToolsSection,sec" />
</configSections>
<CalibrationToolsSection>
<!-- This section contains the calibration tools' loading-enabling options, and versioning parameters as follows:
toolname - the calibration tool's name as returned by GetName() in ICalibrationPlugin (for static tool) or as appears in the records (for auto-gen tool)
isvisible - if set to "false" the tool will not be loaded. Deafult value: true
version - if set to "false" the tool will not be loaded. Deafult value: true /-->
<!--IpuToolCalibration-->
<IpuToolCalibrations>
<add ipu="p1">
<CalibrationToolsLoadingSettings>
<add toolname="AE" version="1" isvisible="false"/>
<add toolname="AE2" version="1" isvisible="true"/>
</CalibrationToolsLoadingSettings>
</add>
<add ipu="p2">
<CalibrationToolsLoadingSettings>
<add toolname="AE" version="1" isvisible="false"/>
<add toolname="AE2" version="1" isvisible="true"/>
</CalibrationToolsLoadingSettings>
</add>
<add ipu="p3">
<CalibrationToolsLoadingSettings>
<add toolname="AE" version="1" isvisible="false"/>
<add toolname="AE2" version="1" isvisible="true"/>
</CalibrationToolsLoadingSettings>
</add>
<add ipu="p4">
<CalibrationToolsLoadingSettings>
<add toolname="AE" version="1" isvisible="false"/>
<add toolname="AE2" version="1" isvisible="true"/>
</CalibrationToolsLoadingSettings>
<PalAteConnectivitySettings>
<add pal-uuid="1111" connect-ate="true" name="p4_wb" />
<add pal-uuid="2222" connect-ate="true" name="p4_lsc" />
<add pal-uuid="3333" connect-ate="true" name="p4_blc" />
<add pal-uuid="4343" connect-ate="true" name="p4_disparity" />
<add pal-uuid="9999" connect-ate="true" name="p4_gridbaseob" />
</PalAteConnectivitySettings>
</add>
<add ipu="p5">
<CalibrationToolsLoadingSettings>
<add toolname="ACMCmc" version="1" isvisible="true"/>
<add toolname="ACM3A" version="1" isvisible="true"/>
<add toolname="AE" version="1" isvisible="false"/>
<add toolname="AE2" version="1" isvisible="true"/>
<add toolname="llolo" version="1" isvisible="true" />
<add toolname="lalla" version="1" isvisible="true" />
</CalibrationToolsLoadingSettings>
<PalAteConnectivitySettings>
<add pal-uuid="32398" connect-ate="true" name="p5_wb" />
<add pal-uuid="53711" connect-ate="true" name="p5_lsc" />
<add pal-uuid="40661" connect-ate="true" name="p5_blc" />
<add pal-uuid="55093" connect-ate="true" name="p5_disparity" />
<add pal-uuid="46517" connect-ate="true" name="p5_gridbaseob" />
</PalAteConnectivitySettings>
</IpuToolCalibrations>
</CalibrationToolsSection>
<appSettings>
<add key="DisableCalibrationCheck" value="false" />
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
我看到你可以动态创建集合,例如
ConfigurationManager.AppSettings["mykey"] = "myvalue";
现在我正在使用这样的类使用System.Configuration;
namespace Manager.Calibration.Configuration
{
public class CalibrationToolsSection : ConfigurationSection
{
public static readonly string CALIBRATION_SECTION_NAME = "CalibrationToolsSection";
[ConfigurationProperty("IpuToolCalibrations")]
public IpuToolCalibrationCollection IpuToolCalibrations
{
get
{
return ((IpuToolCalibrationCollection)this["IpuToolCalibrations"]);
}
set
{
this["IpuToolCalibrations"] = value;
}
}
}
}
和
public class IpuToolCalibrationCollection : ConfigurationElementCollection
{
public IpuToolCalibration this[int index]
{
get { return base.BaseGet(index) as IpuToolCalibration; }
set
{
if (base.BaseGet(index) != null)
{
base.BaseRemoveAt(index);
}
this.BaseAdd(index, value);
}
}
protected override ConfigurationElement CreateNewElement()
{
return new IpuToolCalibration();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((IpuToolCalibration)element).Ipu;
}
}
等等
public class IpuToolCalibration : ConfigurationElement
{
public static readonly string IPU_TOOL_CALIBRATION_SECTION_NAME = "IpuToolCalibration";
[ConfigurationProperty("ipu", IsRequired = true)]
public string Ipu
{
get { return (string)this["ipu"]; }
set { this["ipu"] = value; }
}
[ConfigurationProperty("CalibrationToolsLoadingSettings")]
public ToolSettingElementCollection ToolsLoadingSettingsCollection
{
get
{
return ((ToolSettingElementCollection)this["CalibrationToolsLoadingSettings"]);
}
set
{
this["CalibrationToolsLoadingSettings"] = value;
}
}
[ConfigurationProperty("PalAteConnectivitySettings")]
public FilterAteConnectivityElementCollection PalAteConnectivityCollection
{
get
{
return ((FilterAteConnectivityElementCollection)this["PalAteConnectivitySettings"]);
}
set
{
this["PalAteConnectivitySettings"] = value;
}
}
}
}
谁能解释我如何从代码中创建这些,因为它们都是没有构造函数的静态类,我该如何模拟它们,我使用NSubstitute。例如,如果我想加载部分插件而不是全部?
我认为,任何时候当你面对单元测试任何一段有静态实现的代码时,你都需要创建某种包装器,然后可以在需要的地方注入——在某种程度上,这是一种"装饰器模式"的变体。我提供的代码示例只是为了说明这一点:
public class FileReaderService : IFileReaderService
{
public string GetFileAsString(string fileName)
{
if(!File.Exists(fileName))
throw new ArgumentException("File Path does not exist.");
return File.ReadAllText(fileName);
}
}
public interface IFileReaderService
{
string GetFileAsString(string fileName);
}
我正在包装静态函数File。ReadAllText与一个名为FileReaderService的服务,并有一个接口IFileReaderService。现在我可以在任何需要它的地方注入服务,然后能够相应地模拟和编写单元测试。我希望这能给你一个想法,如何重构你的代码来做几乎相同的。