我使用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引用一个不属于模拟对象的方法”
我该如何解决这个问题?
我是使用SetupGet方法完成的,如下所示。它适用于我,希望它有所帮助。
_configurationRoot = new Mock<IConfigurationRoot>();
_configurationRoot.SetupGet(x => x[It.IsAny<string>()]).Returns("the string you want to return");
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
ConfigurationManager.Configuration = builder.Build();
我认为你的方法是构建可模拟的代理扩展方法,并使用它们。本地扩展方法可以覆盖外部方法,因此您可以创建自己的扩展类:
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");