问题
I have used IConfigurationRoute to access a directory like this.
if (type == "error") directory = _config.GetValue<string>("Directories:SomeDirectory");
_config is IConfigurationRoot injected in the constructor.
I tried the following way to mock it.
var mockConfigurationRoot = new Mock<IConfigurationRoot>();
mockConfigurationRoot.Setup(c => c.GetValue<string>("Directories: SomeDirectory"))
.Returns("SomeDirectory")
.Verifiable();
var config = mockConfigurationRoot.Object;
The issue is while running the test Xunit throws the exception saying
"System.NotSupportedException : Expression references a method that does not belong to the mocked object"
How can I solve this issue?
回答1:
I did it using the SetupGet method as follows. It works for me, hope it helps.
_configurationRoot = new Mock<IConfigurationRoot>();
_configurationRoot.SetupGet(x => x[It.IsAny<string>()]).Returns("the string you want to return");
回答2:
Copy the appSettings.json to your Test project root directory and mark it's property as Content and Copy if newer.
var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddEnvironmentVariables(); ConfigurationManager.Configuration = builder.Build();
ConfigurationManager is a class and it has a static property Configuration. This way the whole application can just access it as ConfigurationManager.Configuration[]
回答3:
I think the way you'd do it is to build mockable proxy extension methods, and use those, instead. Local extension methods can override external methods, so you can create your own extensions class:
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);
}
Then, setup your proxy:
public class ConfigurationProxy : IConfigurationProxy
{
public T GetValue<T>(IConfigurationRoot config, string key) => config.GetValue<T>(key);
}
Now, in each class where you want to use mockable extension methods, add a static constructor:
static MyClass()
{
ConfigurationExtensions.Proxy = new ConfigurationProxy();
}
Or
static MyClass_Tests()
{
ConfigurationExtensions.Proxy = Mock.Of<IConfigurationProxy>();
}
Wash, rinse, repeat for each extension method you need to use. More explanation can be found, here: http://blogs.clariusconsulting.net/kzu/how-to-design-a-unit-testable-domain-model-with-entity-framework-code-first/
Also, in case its helpful, you can also mock the dictionary's getter:
mockConfigurationRoot.SetupGet(m => m["ConnectionStrings:Repository"]).Returns("bogus");
来源:https://stackoverflow.com/questions/43618686/how-to-setup-mock-of-iconfigurationroot-to-return-value