[英]How to update the properties of already registered class in Autofac container in Nunit Framework
I use a dependency injection framework AutoFac
in NUnit
as described here 我使用依赖注入框架
AutoFac
在NUnit
描述在这里
The classes are registered as SingleInstance scope. 这些类被注册为SingleInstance范围。
one of the classes depends on Setting
class, as given below: 其中一个类取决于
Setting
类,如下所示:
class Product
{
public (Setting setting, Dep1 dependency) {.... }
....
}
I want to update the properties of one of the classes "Setting" per test case. 我想针对每个测试用例更新“设置”类之一的属性。
[Test]
public void Test()
{
//Arrange
var setting = Resolve<Setting>
Setting.Id = value
// product depend on two dependency injected via constructor
var product = Resolve<Product> ;
//the problem is: the new values of setting class are not reflected in
//Product, and the Product still use the default values provided by the container
......
}
The problem is the updated value is not reflected in the container and unit test fail and the Product
class still use the default values
问题是更新的值未反映在容器中,并且单元测试失败,并且
Product
类仍使用default values
I tried to use this solution , but it can't help.The Documentation of AutoFac don't provide guidelines of using in NUnit or test suite. 我试图用这个解决方案 ,但它不能主动帮助的文档AutoFac不提供使用NUnit的或测试套件的指导方针。
The question: How can I update the values of the class setting
and the new values are auto injected in the constructor of product
class in NUnit ? 问题:如何更新类
setting
的值,并将新值自动注入NUnit中product
类的构造函数中?
You don't. 你不知道
Each application should have its own Composition Root . 每个应用程序应具有其自己的“ 合成根” 。 Since a test project is a separate application from the class under test, you would never share a production configuration with a test configuration .
由于测试项目是与被测类不同的应用程序,因此您永远不会与测试配置共享生产配置 。
When unit testing, you typically don't deal with more than half a dozen or so dependencies at a time. 在进行单元测试时,通常一次不会处理超过六个左右的依赖项。 It would be impractical to setup a DI container for this purpose.
为此目的设置DI容器是不切实际的。 Instead, you should new up the class under test and mock everything else except for DTO and Model objects.
取而代之的是,您应该重新建立被测类并模拟除DTO和Model对象之外的所有其他内容。
[Test]
public void Test()
{
var setting = new Setting { Value1 = "x", Value2 = "y" };
var dep1 = new Mock<Dep1>();
// setup Moq conditions on dep1
var product = new Product(setting, dep1);
// Execute method on product and assert
}
When integration testing, it is also better to use pure DI than to setup a DI container just for the purpose of testing. 在进行集成测试时,使用纯DI比仅出于测试目的设置DI容器要好。 However, if you do use a DI container, it should have its own configuration separate from the application that is being tested.
但是,如果您确实使用DI容器,则它应具有与正在测试的应用程序不同的独立配置。 Even if this weren't considered a bad practice, there will be dependencies that need to be mocked that warrant this anyway.
即使这不是不好的做法,还是有一些需要嘲笑的依赖关系仍然可以保证这样做。 You are not testing the DI container configuration, you are testing the components of your application , so there is no need to make them one and the same.
您不是在测试DI容器配置,而是在测试应用程序的组件 ,因此无需使它们相同。
NOTE: It is strongly advised to use abstractions rather than concrete types as constructor parameters.
注意:强烈建议使用抽象而不是具体类型作为构造函数参数。 The usual route is to use interfaces (although I would argue that "settings" might not need to be), but abstract classes will also work.
通常的途径是使用接口(尽管我认为可能不需要“设置”),但是抽象类也可以使用。
Instead of trying to update the properties of your Settings
class, you can create an interface to represent your settings, like 您可以创建一个界面来表示您的设置,而不是尝试更新
Settings
类的属性,例如
public interface ISettings
{
int Value { get; }
}
Inject that interface, not a concrete class, into your Product
class. 将该接口(而不是具体的类)注入到
Product
类中。 Your concrete implementation might read from a configuration file, or you could have an implementation with hard-coded values - whatever you need. 您的具体实现可以从配置文件中读取,或者您可以使用带有硬编码值的实现-无论您需要什么。
But now that your class depends on that interface, for testing you have a number of options for mocking it. 但是,既然您的类依赖于该接口,为了进行测试,您可以使用许多模拟它的选项。
You could use a test double, like: 您可以使用双重测试,例如:
public class SettingsDouble : ISettings
{
public int Value { get; set; }
}
Or you could use Moq . 或者您可以使用Moq 。
var settingsMock = new Mock<ISettings>();
settingsMock.Setup(x => x.Value).Returns(1);
A side effect is that your ISettings
interface and implementations can have read-only properties. 副作用是您的
ISettings
接口和实现可以具有只读属性。 Chances are that you don't want classes setting those properties at runtime and affecting other classes' settings, but you made it writable for the purpose of unit testing. 可能是您不想让类在运行时设置这些属性并影响其他类的设置,但是您出于单元测试的目的而将其设置为可写。 Now you don't have to do that.
现在,您不必这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.