当你们对依赖app.config文件中的值的应用程序进行单元测试时?如何测试这些值是否正确读入以及程序如何对输入到配置文件中的错误值做出反应?
必须修改NUnit应用程序的配置文件是荒谬的,但是我无法读取我要测试的app.config中的值。
编辑:我想我应该澄清一下。我并不担心ConfigurationManager无法读取值,但我担心测试我的程序如何对读入的值做出反应。
答案 0 :(得分:44)
我通常会隔离外部依赖项,例如在自己的Facade类中读取配置文件,但功能非常少。在测试中,我可以创建这个类的模拟版本,实现并使用它而不是真正的配置文件。您可以创建自己的模型或使用像moq或rhino模拟这样的框架。
通过这种方式,您可以轻松地尝试使用不同配置值的代码,而无需编写首先编写xml配置文件的复杂测试。读取配置的代码通常非常简单,只需要很少的测试。
答案 1 :(得分:31)
您可以在测试设置中在运行时修改配置部分。 E.g:
// setup
System.Configuration.Configuration config =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.Sections.Add("sectionname", new ConfigSectionType());
ConfigSectionType section = (ConfigSectionType)config.GetSection("sectionname");
section.SomeProperty = "value_you_want_to_test_with";
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("sectionname");
// carry out test ...
您当然可以设置自己的辅助方法来更优雅地完成此任务。
答案 2 :(得分:24)
您可以调用ConfigurationManager.AppSettings的set方法来设置特定单元测试所需的值。
[SetUp]
public void SetUp()
{
ConfigurationManager.AppSettings.Set("SettingKey" , "SettingValue");
// rest of unit test code follows
}
当单元测试运行时,它将使用这些值来运行代码
答案 3 :(得分:16)
您可以使用app.config
类
ConfigurationManager
文件
答案 4 :(得分:11)
我遇到了与web.config类似的问题....我找到了一个有趣的解决方案。您可以封装配置读取功能,例如像这样的东西:
public class MyClass {
public static Func<string, string>
GetConfigValue = s => ConfigurationManager.AppSettings[s];
//...
}
然后通常使用
string connectionString = MyClass.GetConfigValue("myConfigValue");
但在单元测试中初始化“覆盖”这样的函数:
MyClass.GetConfigValue = s => s == "myConfigValue" ? "Hi", "string.Empty";
更多信息:
http://rogeralsing.com/2009/05/07/the-simplest-form-of-configurable-dependency-injection/
答案 5 :(得分:3)
更优雅的解决方案是在配置设置本身上使用普通旧依赖注入。恕我直言,这比模拟配置读取类/包装器等更清晰。
例如,假设“天气”类需要“ServiceUrl”才能运行(例如,假设它调用Web服务来获取天气)。而不是让某些代码行主动进入配置文件以获取该设置(无论该代码是在Weather类中还是可以根据其他一些响应进行模拟的单独配置阅读器),Weather类可以允许要注入的设置,可以通过参数传递给构造函数,也可以通过属性设置器注入。这样,单元测试非常简单直接,甚至不需要模拟。
然后可以使用Inversion of Control(或Dependency Injection)容器注入设置的值,因此Weather类的使用者不需要从某处显式提供值,因为它由容器处理。
答案 6 :(得分:2)
这对我有用:
public static void BasicSetup()
{
ConnectionStringSettings connectionStringSettings =
new ConnectionStringSettings();
connectionStringSettings.Name = "testmasterconnection";
connectionStringSettings.ConnectionString =
"server=localhost;user=some;database=some;port=3306;";
ConfigurationManager.ConnectionStrings.Clear();
ConfigurationManager.ConnectionStrings.Add(connectionStringSettings);
}
答案 7 :(得分:1)
您始终可以将读入位包装在接口中,并从配置文件中读取特定的实现。然后,您将使用Mock Objects编写测试,以查看程序如何处理错误值。 就个人而言,我不会测试这个特定的实现,因为这是.NET Framework代码(我假设 - 希望 - MS已经测试过它了。)
答案 8 :(得分:1)
System.Configuration.Abstractions在测试这类东西时非常有用。
以下是GitHub项目网站,其中包含一些很好的示例:enter link description here
以下是NuGet网站:https://www.nuget.org/packages/System.Configuration.Abstractions/
我几乎在所有.NET项目中都使用它。
答案 9 :(得分:0)
实际上,进一步思考它,我想我应该做的是创建一个ConfigFileReader类,以便在我的项目中使用,然后在单元测试工具中伪造它?
这是平常的事吗?
答案 10 :(得分:0)
最简单的选择是包装读取配置的方法,以便在测试期间替换值。创建一个用于读取配置的接口,并将该接口的实现作为构造函数参数传入或作为属性设置在对象上(就像使用依赖注入/控制反转一样)。在生产环境中,传入一个真正从配置中读取的实现;在测试环境中,传入一个返回已知值的测试实现。
如果你没有选择重构可测试性的代码但仍然需要测试它,那么Typemock Isolator提供了实际模拟.NET框架配置类的能力,所以你可以说“下次我要求这样做 - 并且这样的appSettings值,返回这个已知值。“
答案 11 :(得分:0)
我有同样的问题,
你可以使用Nunit-console.exe c:\ path1 \ testdll1.dll c:\ path2 \ testdll2.dll
即使两个dll指向不同的app.configs,这也能正常工作 ex testdll1.dll.config和testdll2.dll.config
如果你想使用Nunit项目配置并包装这两个dll那么就没有办法让你有两个配置
如果你的Nunit项目是Project1.nunit,那么你必须拥有project1.config,它与Project1.nunit所在的位置相同。
希望这会有所帮助
答案 12 :(得分:0)
嗯,我刚遇到同样的问题...... 我想测试一个从网站引用的BL项目。 但我只想测试BL。因此,在测试项目的预构建事件中,我将app.Config文件复制到bin \ debug文件夹中,并从app.config中引用它们。