Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 模拟自定义配置类_C#_Asp.net Core_Moq_Xunit_Azure Function App - Fatal编程技术网

C# 模拟自定义配置类

C# 模拟自定义配置类,c#,asp.net-core,moq,xunit,azure-function-app,C#,Asp.net Core,Moq,Xunit,Azure Function App,我有一个自定义类用于读取Azure Function App v2中的配置值: public class Config { public string Key1 { get; set; } public string Key2 { get; set; } public Config() { this.Key1 = Environment.GetEnvironmentVariable("abc"); this.Key2 = Envi

我有一个自定义类用于读取Azure Function App v2中的配置值:

public class Config
{
    public string Key1 { get; set; }
    public string Key2 { get; set; }

    public Config()
    {
        this.Key1 = Environment.GetEnvironmentVariable("abc");
        this.Key2 = Environment.GetEnvironmentVariable("xyz");
    }
}
我已经在
Startup.cs
类的
Configure
方法中注册了它,如下所示:

builder.Services.AddSingleton((s) =>
{
    return new Config();
});
现在,当我试图模拟这个
Config.cs
类并设置其键的值时,它抛出错误:

var mockConfiguration = new Mock<Config>();
mockConfiguration.Setup(m => m.Key1).Returns("value");
var mockConfiguration=new Mock();
Setup(m=>m.Key1).返回(“值”);

我使用
XUnit
作为测试框架,使用
MOQ
进行模拟。如果我不想为我的配置类创建一个接口,还有什么方法可以模拟它呢?

这源于一个初始设计问题

Config
类与实现问题紧密耦合

Environment.GetEnvironmentVariable
在隔离测试时不存在,并导致异常

正如评论中准确指出的,您应该利用配置模块并注册配置,而不是紧密耦合到
环境

参考:

并将
IOptions
显式注入subject函数

private readonly Config config;
//ctor
public MyFunction(IOptions<Config> options) { 
    config = options.Value;

    //...
}
因此,允许对功能进行隔离测试,而不会因实现问题而产生不必要的副作用

//Arrange
var mockConfiguration = new Config() {
    Key1 = "value"
};

var subject = new MyFunction(mockConfiguration);

//...

当然,它不会让您模拟它,因为属性是非虚拟的(我假设通过阅读错误消息,您应该知道这一点)。通过继承类(或接口)并用模拟代码重写/实现属性,模拟可以工作。无论哪种方式,您都应该重构类以使其更易于重构,而接口是实现这一点的一种方法。如果您开始在代码的其他部分更新或使用静态类,您将越来越多地遇到此类问题,原因是软件设计不好。此外,不清楚您为什么不使用选项模式(
IOptions
class with
.Configure(options=>options.Key1=Environment.GetEnvironmentVariable(“abc”))
,然后将
IOptions
)注入到您的类中,您将永远不会出现这种情况
private readonly Config config;
//ctor
public MyFunction(IOptions<Config> options) { 
    config = options.Value;

    //...
}
builder.Services.Configure<Config>(options => {
    options.Key1 = Environment.GetEnvironmentVariable("abc");
    options.Key2 = Environment.GetEnvironmentVariable("xyz");
});    
builder.Services.AddSingleton((s) => {
    return s.GetRequiredService<IOptions<Config>>().Value;
});
//ctor
public MyFunction(Config config) { 
    //...
}
//Arrange
var mockConfiguration = new Config() {
    Key1 = "value"
};

var subject = new MyFunction(mockConfiguration);

//...