61

当你们对依赖于 app.config 文件中的值的应用程序进行单元测试时?您如何测试这些值是否被正确读取,以及您的程序如何对输入到配置文件中的错误值做出反应?

不得不修改 NUnit 应用程序的配置文件是荒谬的,但我无法从我想测试的 app.config 中读取值。

编辑:我想我应该澄清一下。我不担心 ConfigurationManager 无法读取值,但我关心的是测试我的程序如何对读取的值做出反应。

4

13 回答 13

46

我通常隔离外部依赖项,例如在他们自己的外观类中读取配置文件,功能很少。在测试中,我可以创建这个类的模拟版本,它实现并使用它而不是真正的配置文件。您可以为此创建自己的模型或使用 moq 或 rhino 模型之类的框架。

这样,您可以轻松地尝试使用不同配置值的代码,而无需编写首先编写 xml 配置文件的复杂测试。读取配置的代码通常非常简单,几乎不需要测试。

于 2008-10-03T21:16:03.573 回答
31

您可以在运行时在测试设置中修改配置部分。例如:

// 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 ...

您当然可以设置自己的辅助方法来更优雅地执行此操作。

于 2008-11-01T16:03:10.390 回答
26

您可以调用 ConfigurationManager.AppSettings 的 set 方法来设置该特定单元测试所需的值。

[SetUp]
public void SetUp()
{
  ConfigurationManager.AppSettings.Set("SettingKey" , "SettingValue");
  // rest of unit test code follows
}

当单元测试运行时,它将使用这些值来运行代码

于 2010-12-22T16:02:13.690 回答
16

您可以使用该类读取和写入app.config文件ConfigurationManager

于 2008-10-03T21:12:14.797 回答
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/

于 2009-05-19T15:06:38.560 回答
3

一个更优雅的解决方案是在配置设置本身上使用普通的旧依赖注入。恕我直言,这比必须模拟配置读取类/包装器等更干净。

例如,假设“天气”类需要“ServiceUrl”才能运行(例如,它调用 Web 服务来获取天气)。与其让某些代码行主动转到配置文件以获取该设置(无论该代码是在 Weather 类中还是可以根据其他一些响应模拟的单独配置读取器中),Weather 类可以允许要注入的设置,要么通过构造函数的参数,要么可能通过属性设置器。这样,单元测试就非常简单直接,甚至不需要模拟。

然后可以使用控制反转(或依赖注入)容器注入设置的值,因此 Weather 类的使用者不需要从某个地方显式提供值,因为它是由容器处理的。

于 2009-09-22T22:29:57.127 回答
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);
  }
于 2010-03-27T06:48:43.697 回答
1

您始终可以将读入位包装在接口中,并从配置文件中读取特定的实现。然后,您将使用 Mock Objects 编写测试以查看程序如何处理错误值。就个人而言,我不会测试这个特定的实现,因为这是 .NET Framework 代码(我假设 - 希望 - MS 已经对其进行了测试)。

于 2008-10-03T21:13:48.740 回答
1

在测试这类东西时,System.Configuration.Abstractions 是一件美妙的事情。

这是 GitHub 项目站点,其中包含一些很好的示例:在此处输入链接描述

这是 NuGet 站点:https ://www.nuget.org/packages/System.Configuration.Abstractions/

我在几乎所有的 .NET 项目中都使用它。

于 2015-05-11T13:19:30.783 回答
0

实际上,进一步考虑,我想我应该做的是创建一个 ConfigFileReader 类以在我的项目中使用,然后在单元测试工具中伪造它?

这是通常的做法吗?

于 2008-10-03T21:12:02.317 回答
0

最简单的选项是包装读取配置的方法,以便您可以在测试期间替换值。创建一个用于读取配置的接口,并让该接口的实现作为构造函数参数传入或在对象上设置为属性(就像使用依赖注入/控制反转一样)。在生产环境中,传入一个真正从配置中读取的实现;在测试环境中,传入一个返回已知值的测试实现。

如果您没有为可测试性重构代码的选项,但仍需要对其进行测试,Typemock Isolator 提供了实际模拟 .NET 框架配置类的能力,因此您可以说“下次我要求这样和-这样的 appSettings 值,返回这个已知值。”

于 2008-10-03T21:43:51.737 回答
0

我遇到过同样的问题,

你可以使用 Nunit-console.exe c:\path1\testdll1.dll c:\path2\testdll2.dll

即使两个 dll 都指向不同的 app.config,例如 testdll1.dll.config 和 testdll2.dll.config,这也能正常工作

如果您想使用 Nunit 项目配置并包装这两个 dll,那么您将无法拥有两个配置

如果您的 Nunit 项目是 project1.nunit 与 Project1.nunit 所在的位置相同,则您必须拥有 project1.config。

希望这可以帮助

于 2008-10-30T07:36:26.907 回答
0

好吧,我只是遇到了同样的问题......我想测试一个从网站引用的 BL 项目。但我只想测试 BL。因此,在测试项目的预构建事件中,我将 app.Config 文件复制到 bin\debug 文件夹中,并从 app.config 中引用它们...

于 2015-04-13T08:20:42.340 回答