How to setup Mock of IConfigurationRoot to return value

33,597

Solution 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");

Solution 2

  1. Copy the appSettings.json to your Test project root directory and mark it's property as Content and Copy if newer.

  2. var builder = new ConfigurationBuilder()
          .SetBasePath(Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
          .AddEnvironmentVariables();
    ConfigurationManager.Configuration = builder.Build();
    
  3. ConfigurationManager is a class and it has a static property Configuration. This way the whole application can just access it as ConfigurationManager.Configuration[]

Solution 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");
Share:
33,597

Related videos on Youtube

Shaurav Adhikari
Author by

Shaurav Adhikari

Updated on February 13, 2020

Comments

  • Shaurav Adhikari
    Shaurav Adhikari over 4 years

    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?

    • Patrick Quirk
      Patrick Quirk about 7 years
    • Nkosi
      Nkosi about 7 years
      You are trying to mock an extension method, which Moq is unable to do.
    • Shaurav Adhikari
      Shaurav Adhikari about 7 years
      Thanks for the comments. But what is the way around, I mean how are people in the industry doing it? I was not able to use Fakes in .net core. I could not find solution, I'm new to .net.
  • Oli
    Oli over 6 years
    Simple and effective, just what I was looking for!
  • Peter Ritchie
    Peter Ritchie over 5 years
    ConfigurationBuilder exists, why would you want to do that to yourself?
  • DanielV
    DanielV over 5 years
    I tried to mock the "IConfiguration" to get the "GetConnectionString" method with my own connection string. It didn't work.
  • Gracie
    Gracie over 5 years
    This does not appear to work. An alternative is not to mock at all: builder.AddInMemoryCollection(new Dictionary<string, string> { { "ConnectionStrings:DB", "MyConnection" }, { "MyKey", "MyValue" } }); var config = builder.Build();
  • Ciarán Bruen
    Ciarán Bruen about 4 years
    @PeterRitchie ConfigurationBuilder exists but requires including the appsettings.json file and ensuring it gets copied. Mocking it is easier for simple scenarios like this imo
  • Ahmad
    Ahmad almost 4 years
    Won't work in many cases, like when using .Get<T> extension method.