我使用IConfigurationRoute来访问这样的目录。
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引用一个方法 不属于模拟对象“
我该如何解决这个问题?
答案 0 :(得分:5)
将appSettings.json复制到Test项目根目录,并将其标记为内容,如果更新则将其标记为复制。
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
ConfigurationManager.Configuration = builder.Build();
ConfigurationManager是一个类,它具有静态属性Configuration。这样整个应用程序就可以像ConfigurationManager.Configuration []
答案 1 :(得分: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");