在单元测试中修改应用程序设置
我有一个类库,我想使用 Microsoft 的单元测试框架进行单元测试。我想要测试的一些类是使用应用程序设置进行配置的。这些设置在 Settings.settings
文件中定义,具有应用程序范围和合适的默认值。当应用程序使用该库时,可以在 App.Config 文件中覆盖这些设置。如果不是,则使用默认值。这正是我想要的。
在我的一些测试用例中,我想测试设置值的特殊组合,但我不知道如何更改单元测试代码中被测类看到的值。这些设置将始终从代码生成的类的属性中加载默认值。
在我的库类中,我访问如下设置:
var mySetting1 = Settings.Default.MySetting1;
var mySetting2 = Settings.Default.MySetting2;
在被测试的类访问设置之前,如何在单元测试中修改这些设置?使单元测试可访问内部设置类并不能解决问题,因为设置具有应用程序范围并且是设置类上的只读属性。
I have a class library I want to unit test using Microsofts unit test framework. Some of the classes I want to test are configured using application settings. These settings are defined inside the Settings.settings
file having application scope and suitable default values. When the library is used by the application these settings can be overriden in the App.Config
file. If not the default values are used. That's exactly how I want it to be.
In some of my test cases I want to test special combinations of setting values but I don't know how to change the values seen by the class under test from the unit test code. These settings will always have their default value loaded from the attributes of the code generated class.
In my library class I access the settings like this:
var mySetting1 = Settings.Default.MySetting1;
var mySetting2 = Settings.Default.MySetting2;
How do I modify these settings in an unit test before the setting is accessed by the class under test? Making the internal settings class accessible by the unit test does not solve the problem as the settings have application scope and are read-only properties on the settings class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在深入研究
ApplicationSettingsBase
和相关类之后,我想出了这个解决方案来解决我的问题。不是特别漂亮,但它确实能完成工作。代码生成的设置类位于类库项目的内部,并且单元测试项目必须可以访问它。将
[ assembly:InternalsVisibleTo("UnitTestAssemblyName")]
属性添加到类库项目中的AssemblyInfo.cs
中。当访问值时,从设置类上的属性延迟加载设置。第一步是对设置进行“虚拟”读取以强制执行此延迟加载。当单元测试时,您希望避免一个测试中更改的设置值影响另一个测试,因此有必要在延迟加载之前“重置”设置。这可以使用
Reload()
方法来完成。此代码放置在测试初始化方法中:基础值现在存在并且可以在每个测试方法中设置。请记住使用正确的类型,因为代码生成的 getter 将进行强制转换:
After spelunking into the
ApplicationSettingsBase
and associated classes I've come up with this solution to my problem. Not particular beautiful, but it certainly gets the job done.The code generated settings class is internal to the class library project and it has to be accessible to the unit test project. Add the
[assembly: InternalsVisibleTo("UnitTestAssemblyName")]
attribute toAssemblyInfo.cs
in the class library project.The settings are lazy loaded from the attributes on the settings class when a value is accessed. First step is to do a "dummy" read of a setting to force this lazy load. When unit testing you want to avoid settings values changed in one test to affect another hence it is necessary to "reset" the settings before lazy loading them. That can be done using the
Reload()
method. This code is placed in the test initialize method:The underlying values now exist and can be set in each test method. Remember to use the correct type as the code generated getters will do a cast:
我将围绕
Settings
类创建一个包装器类,然后传递该包装器。然后您可以轻松模拟您的设置类。我能想到的唯一的另一件事是稍微更轻量级且更容易模拟的选项,使您的设置文件实现一个反映所有设置的界面。对于调用者来说,这并没有太大的不同,但是在添加新设置时,您需要做的工作会减少。
两者都不是很棒,而且对于自动生成的代码来说必须这样做是很痛苦的,但据我所知,如果您真的想删除对设置文件的依赖,这似乎就是我们所坚持的。
例如,对于包含字符串应用程序设置和 int 用户设置的设置文件:
I'd create a wrapper class around the
Settings
class then pass that wrapper around. Then you can mock away your settings class with ease.The only other thing I can come up with is the slightly more light-weight and easier to mock option of making your settings file implement an interface which reflects all your settings. It's not really much different for the caller, but you'll have less plumbing to do when adding new settings.
Neither is fantastic, and it is a pain to have to do it for auto-generated code, but it seems that's what we're stuck with as far as I can tell if you really want to remove the dependency on the settings file.
E.g. for a settings file containing a string Application setting and an int User setting:
所以你的设置可能会有所不同,但对我有用的是使用 Moq 来模拟 Microsoft.Extensions.Configuration.IConfiguration,如下所示:
So your setup may be different, but what worked for me was using Moq to mock the Microsoft.Extensions.Configuration.IConfiguration like this: