模拟使用索引的 属性

Mocking a property that uses index

我试图解耦 ConfigurationManager 所以我可以模拟它。

这是我的class和界面

public class Settings
{
    public string this[string index] => ConfigurationManager.AppSettings[index];
}

public class ConfigurationRepository : IConfigurationRepository
{    
    public virtual Settings AppSettings
    {
        get { return new Settings(); }
    }
}

public interface IConfigurationRepository
{
   Settings AppSettings { get; }
}

我是这样模拟的

_configurationManager = new Mock<IConfigurationRepository>();
_configurationManager.SetupGet(m => m.AppSettings["someKey"]).Returns("someResult");

但是当我尝试测试它时出现异常

Invalid setup on a non-virtual (overridable in VB) member: m => m.AppSettings["someKey"]

而且测试失败了,它甚至没有通过我的 Setup 方法。

而且我不知道为什么会出现此异常,谁能告诉我我做错了什么?

具体 Settings class 上的索引器 属性 需要 virtual 才能使 Moq 能够覆盖其默认行为

public class Settings {
    public virtual string this[string index] => ConfigurationManager.AppSettings[index];
}

我还建议重构存储库实现,以避免每次调用 AppSettings 属性 时都初始化 class。

public class ConfigurationRepository : IConfigurationRepository {
    private Lazy<Settings> settings = new Lazy<Settings>(() => new Settings());

    public virtual Settings AppSettings {
        get { return settings.Value; }
    }
}