如何设置IConfigurationRoot模拟返回值[重复]

问题描述 投票:8回答:3

我使用IConfigurationRoot来访问这样的目录。

if (type == "error") directory = _config.GetValue<string>("Directories:SomeDirectory");

_config是在构造函数中注入的IConfigurationRoot。

我尝试了以下方式来模拟它。

        var mockConfigurationRoot = new Mock<IConfigurationRoot>();
        mockConfigurationRoot.Setup(c => c.GetValue<string>("Directories: SomeDirectory"))
            .Returns("SomeDirectory")
            .Verifiable();
        var config = mockConfigurationRoot.Object;

问题是在运行测试时,Xunit会抛出异常说法

“System.NotSupportedException:Expression引用一个不属于模拟对象的方法”

我该如何解决这个问题?

c# unit-testing asp.net-core moq xunit.net
3个回答
21
投票

我是使用SetupGet方法完成的,如下所示。它适用于我,希望它有所帮助。

_configurationRoot = new Mock<IConfigurationRoot>();
_configurationRoot.SetupGet(x => x[It.IsAny<string>()]).Returns("the string you want to return");

8
投票
  1. 将appSettings.json复制到Test项目根目录,并将其属性标记为Content and Copy if new。
  2. var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddEnvironmentVariables(); ConfigurationManager.Configuration = builder.Build();
  3. ConfigurationManager是一个类,它具有静态属性Configuration。这样整个应用程序就可以像ConfigurationManager.Configuration []一样访问它。

1
投票

我认为你的方法是构建可模拟的代理扩展方法,并使用它们。本地扩展方法可以覆盖外部方法,因此您可以创建自己的扩展类:

public static class ConfigurationExtensions
{
    public static IConfigurationProxy Proxy = new ConfigurationProxy();
    public static T GetValue<T>(this IConfigurationRoot config, string key) => Proxy.GetValue<T>(config, key);
}

然后,设置您的代理:

public class ConfigurationProxy : IConfigurationProxy
{
    public T GetValue<T>(IConfigurationRoot config, string key) => config.GetValue<T>(key);
}

现在,在要使用可模拟扩展方法的每个类中,添加一个静态构造函数:

static MyClass()
{
    ConfigurationExtensions.Proxy = new ConfigurationProxy();
}

要么

static MyClass_Tests()
{
    ConfigurationExtensions.Proxy = Mock.Of<IConfigurationProxy>();
}

对于需要使用的每种延伸方法,请进行清洗,冲洗,重复。可以在这里找到更多解释:http://blogs.clariusconsulting.net/kzu/how-to-design-a-unit-testable-domain-model-with-entity-framework-code-first/

另外,如果它有用,你也可以模拟字典的getter:

mockConfigurationRoot.SetupGet(m => m["ConnectionStrings:Repository"]).Returns("bogus");
© www.soinside.com 2019 - 2024. All rights reserved.