简体   繁体   English

如何在Nunit Framework中的Autofac容器中更新已注册类的属性

[英]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 我使用依赖注入框架AutoFacNUnit描述在这里

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的值,并将新值自动注入NUnitproduct类的构造函数中?

The Short Answer 简短答案

You don't. 你不知道

The Long Answer 长答案

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.

相关问题 如何在运行时更新Autofac容器中的注册实例 - How to update registered instances in Autofac container in runtime Autofac:根据已注册的项目向容器添加新类型 - Autofac: add new types to container based on already registered items 未为Autofac容器注册为WCF配置的autofac wcf - autofac wcf configured for WCF is not registered with the Autofac container 如何从 autofac 容器解析依赖项(在嵌套的 LifetimeScope 中注册) - How can a dependency (registered in nested LifetimeScope) be resolved from autofac container 在构建我的 Autofac 容器时,如何将以前注册的类型作为参数包含在其他注册类型中? - When building my Autofac container, how do I include previously registered types as parameters in other registered types? 已注册服务中的Autofac属性注入 - Autofac Property Injection in already registered service Autofac服务未注册(Microsoft Bot Framework) - Autofac service not registered (Microsoft Bot Framework) 如何从 .NET Core 3.1 中的 Autofac 容器解析已注册的依赖项 - How can I resolve a registered Dependency from an Autofac Container in .NET Core 3.1 Autofac 容器更新和 Mock 依赖项 - Autofac Container Update and Mock dependencies 如何处理Autofac容器? - How to dispose of Autofac container?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM