使用 NUnit 对 app.config 文件进行单元测试

发布于 2024-07-06 07:19:06 字数 236 浏览 8 评论 0原文

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

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

编辑:我想我也许应该澄清一下。 我并不担心 ConfigurationManager 无法读取这些值,但我关心的是测试我的程序对读入的值的反应。

When you guys are unit testing an application that relies on values from an app.config file? How do you test that those values are read in correctly and how your program reacts to incorrect values entered into a config file?

It would be ridiculous to have to modify the config file for the NUnit app, but I can't read in the values from the app.config I want to test.

Edit: I think I should clarify perhaps. I'm not worried about the ConfigurationManager failing to read the values, but I am concerned with testing how my program reacts to the values read in.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

烟─花易冷 2024-07-13 07:19:06

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

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

I usually isolate external dependencies like reading a config file in their own facade-class with very little functionality. In tests I can create a mock version of this class that implements and use that instead of the real config file. You can create your own mockup's or use a framework like moq or rhino mocks for this.

That way you can easily try out your code with different configuration values without writing complex tests that first write xml-configuration files. The code that reads the configuration is usually so simple that it needs very little testing.

表情可笑 2024-07-13 07:19:06

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

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

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

You can modify your config section at runtime in your test setup. 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 ...

You can of course setup your own helper methods to do this more elegantly.

我最亲爱的 2024-07-13 07:19:06

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

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

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

You can call the set method of ConfigurationManager.AppSettings to set the values required for that particular unit test.

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

When the unit test runs it will then use these values to run the code

懒的傷心 2024-07-13 07:19:06

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

You can both read and write to the app.config file with the ConfigurationManager class

总以为 2024-07-13 07:19:06

我在 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-注入/

I was facing similar problems with web.config.... I find an interesting solution. You can encapsulate configuration reading function, e.g. something like this:

public class MyClass {

public static Func<string, string> 
     GetConfigValue = s => ConfigurationManager.AppSettings[s];

//...

}

And then normally use

string connectionString = MyClass.GetConfigValue("myConfigValue");

but in unit test initialize "override" the function like this:

MyClass.GetConfigValue = s =>  s == "myConfigValue" ? "Hi", "string.Empty";

More about it:

http://rogeralsing.com/2009/05/07/the-simplest-form-of-configurable-dependency-injection/

罪歌 2024-07-13 07:19:06

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

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

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

A more elegant solution is to use plain old dependency injection on the configuration settings themselves. IMHO this is cleaner than having to mock a configuration reading class/wrapper etc.

For example, say a class "Weather" requires a "ServiceUrl" in order to function (e.g. say it calls a web service to get the weather). Rather than having some line of code that actively goes to a configuration file to get that setting (whether that code be in the Weather class or a separate configuration reader that could be mocked as per some of the other responses), the Weather class can allow the setting to be injected, either via a parameter to the constructor, or possibly via a property setter. That way, the unit tests are extremely simple and direct, and don't even require mocking.

The value of the setting can then be injected using an Inversion of Control (or Dependency Injection) container, so the consumers of the Weather class don't need to explicitly supply the value from somewhere, as it's handled by the container.

空气里的味道 2024-07-13 07:19:06

这对我有用:

 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);
  }

That worked for me:

 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);
  }
潜移默化 2024-07-13 07:19:06

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

You can always wrap the reading-in bit in an interface, and have a specific implementation read from the config file. You would then write tests using Mock Objects to see how the program handled bad values.
Personally, I wouldn't test this specific implementation, as this is .NET Framework code (and I'm assuming - hopefully - the MS has already tested it).

北方。的韩爷 2024-07-13 07:19:06

在测试此类内容时,System.Configuration.Abstractions 是一件美妙的事情。

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

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

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

System.Configuration.Abstractions is a thing of beauty when it comes to testing this kind of stuff.

Here is the GitHub project site with some good examples: enter link description here

Here is the NuGet site: https://www.nuget.org/packages/System.Configuration.Abstractions/

I use this in almost all of my .NET projects.

你是暖光i 2024-07-13 07:19:06

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

这是平常的事吗?

Actually, thinking on it further, I suppose what I should do is create a ConfigFileReader class for use in my project and then fake it out in the unit test harness?

Is that the usual thing to do?

甩你一脸翔 2024-07-13 07:19:06

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

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

The simplest option is to wrap the methods that read configuration such that you can substitute in values during testing. Create an interface that you use for reading config and have an implementation of that interface get passed in as a constructor parameter or set on the object as a property (as you would using dependency injection/inversion of control). In the production environment, pass in an implementation that really reads from configuration; in the test environment, pass in a test implementation that returns a known value.

If you don't have the option of refactoring the code for testability yet still need to test it, Typemock Isolator provides the ability to actually mock the .NET framework configuration classes so you can just say "next time I ask for such-and-such appSettings value, return this known value."

小猫一只 2024-07-13 07:19:06

我遇到了同样的问题,

您可以使用 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 位于同一位置。

希望这可以帮助

I had the same issue,

you can use Nunit-console.exe c:\path1\testdll1.dll c:\path2\testdll2.dll

this works fine even though if both dlls point to different app.configs
ex testdll1.dll.config and testdll2.dll.config

if you want to use Nunit project config and wrap these two dlls then there is no way you can have two configs

you have to have project1.config if your Nunit project is project1.nunit in the same location as Project1.nunit sits.

hope this helps

静赏你的温柔 2024-07-13 07:19:06

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

Well, I just had the same problem...
I wanted to test a BL project that is referenced from a web site .
but i wanted to test the BL only. So in the pre-build event of the test project I copy the app.Config files into the bin\debug folder and reference them from the app.config ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文