Jas*_*oyd 18 c# unit-testing app-config application-settings visual-studio
我有一个C#单元测试项目,在app.config文件中有应用程序设置.我正在测试一个存在于不同项目中的类.那个班级取决于两者,ConfigurationManager.AppSettings和ConfigurationManager.ConnectionStrings.
被测试的类所在的项目没有app.config文件.我原以为,因为该类正在单元测试项目的上下文中实例化,它将使用单元测试项目的app.config文件.实际上,连接字符串似乎就是这种情况.
该类检索连接字符串没有任何问题.但是,当类尝试检索任何应用程序设置时,配置管理器始终返回null.这里发生了什么?
编辑1
我想也许在测试项目中尝试加载一些设置以查看会发生什么是个好主意.我试着在调用在外部项目中实例化类的代码之前立即加载单元测试中的设置.同样的结果,没有.我想我暂时可以从等式中排除其他项目.
这是我的配置文件的摘录:
<configSections>
<sectionGroup name="applicationSettings"
type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MyNamespace.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
</sectionGroup>
</configSections>
...
<applicationSettings>
<MyNamespace.Properties.Settings>
<setting name="Bing_Key"
serializeAs="String">
<value>...</value>
</setting>
</MyNamespace.Properties.Settings>
</applicationSettings>
Run Code Online (Sandbox Code Playgroud)
以下是我尝试加载设置的方法:
string test = System.Configuration.ConfigurationManager.AppSettings["Bing_Key"];
Run Code Online (Sandbox Code Playgroud)
xDa*_*vax 10
考虑重构访问配置的代码以使用包装器.然后,您可以为包装类编写模拟,而不必处理导入测试的配置文件.
在两者都很常见的库中,有这样的东西:
public interface IConfigurationWrapper {
string GetValue(string key);
bool HasKey(string key);
}
Run Code Online (Sandbox Code Playgroud)
然后,在需要访问config的库中,将此接口类型的实例注入需要读取config的类中.
public class MyClassOne {
private IConfigurationWrapper _configWrapper;
public MyClassOne(IConfigurationWrapper wrapper) {
_configWrapper = wrapper;
} // end constructor
public void MethodThatDependsOnConfiguration() {
string configValue = "";
if(_configWrapper.HasKey("MySetting")) {
configValue = _configWrapper.GetValue("MySetting");
}
} // end method
} // end class MyClassOne
Run Code Online (Sandbox Code Playgroud)
然后,在其中一个库中,创建一个依赖于配置文件的实现.
public class AppConfigWrapper : IConfigurationWrapper {
public string GetValue(string key) {
return ConfigurationManager.AppSettings(key);
}
public bool HasKey(string key) {
return ConfigurationManager.AppSettings.AllKeys.Select((string x) => x.ToUpperInvariant()).Contains(key.ToUpperInvariant());
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在调用您的类的代码中.
//Some method container
MyClassOne dataClass = new MyClassOne(new AppConfigWrapper());
dataClass.MethodThatDependsOnConfiguration();
Run Code Online (Sandbox Code Playgroud)
然后在你的测试中,你没有依赖束缚.:)你可以创建一个实现IConfigurationWrapper的虚假版本并将其传递给你的测试,你可以从GetValue和HasKey函数硬编码返回值,或者如果你使用像Moq这样的模拟库:
Mock<IConfigurationWrapper> fakeWrapper = new Mock<IConfigurationWrapper>();
fakeWrapper.Setup((x) => x.GetValue(It.IsAny<string>)).Returns("We just bypassed config.");
MyClassOne testObject = new MyClassOne(fakeWrapper.Object);
testObject.MethodThatDependsOnConfiguration();
Run Code Online (Sandbox Code Playgroud)
这篇文章涵盖了这个概念(虽然对于Web表单,但概念是相同的):http://www.schwammysays.net/how-to-unit-test-code-that-uses-appsettings-from织网,配置/
您在项目属性中提到了设置.看看你是否可以这样访问设置:
string test = Properties.Settings.Default.Bing_Key;
Run Code Online (Sandbox Code Playgroud)
您可能需要获取定义项目设置文件的执行程序集,但首先尝试此操作.
编辑
使用Visual Studio的项目设置文件时,它会向app.config添加内容并创建app.config(如果不存在).ConfigurationManager无法触摸这些设置!您只能使用上面的静态方法获取这些特定生成的project.settings文件.如果要使用ConfigurationManager,则需要手动编写app.config.像这样添加你的设置:
<appSettings>
<add key="bing_api" value="whatever"/>
</appSettings>
Run Code Online (Sandbox Code Playgroud)
如果您使用的是 .NET Core,您的问题可能是由于测试进程作为 testhost.dll(或 testhost.x86.dll)运行而导致的已知问题,这意味着运行时配置文件应命名为“testhost .dll.config”(或“testhost.x86.dll.config”),而不是 app.config 输出(例如:“MyLibrary.Tests.dll.config”)。
要修复它,请将以下代码添加到根节点内的项目文件(.csproj 等)中<Project>。在构建过程中,app.config 的两个副本将放在输出目录中,并命名为“testhost.dll.config”和“testhost.x86.dll.config”,这将使您的应用程序设置再次工作。(您只需要这些文件中的 1 个,但同时包含这两个文件更安全。)
<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
<Copy SourceFiles="app.config" DestinationFiles="$(OutDir)\testhost.dll.config" />
<Copy SourceFiles="app.config" DestinationFiles="$(OutDir)\testhost.x86.dll.config" />
</Target>
Run Code Online (Sandbox Code Playgroud)
我只推荐 app.config 作为临时解决方案。如果您像我一样,在将 .NET Framework 项目升级到 .NET Core 时可能会遇到问题,需要快速修复。但不要忘记研究 .NET Core 提供的用于存储应用程序设置的新的、更优雅的解决方案。
| 归档时间: |
|
| 查看次数: |
20700 次 |
| 最近记录: |