26

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?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
Shaurav Adhikari
  • 741
  • 3
  • 10
  • 22
  • See [this question](http://stackoverflow.com/questions/27286125/expression-references-a-method-that-does-not-belong-to-the-mocked-object). – Patrick Quirk Apr 25 '17 at 19:17
  • You are trying to mock an extension method, which Moq is unable to do. – Nkosi Apr 26 '17 at 00:01
  • 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. – Shaurav Adhikari Apr 26 '17 at 17:54

3 Answers3

42

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");
user3130628
  • 497
  • 4
  • 5
  • Simple and effective, just what I was looking for! – Oli Dec 30 '17 at 02:45
  • ConfigurationBuilder exists, why would you want to do that to yourself? – Peter Ritchie Sep 18 '18 at 18:47
  • I tried to mock the "IConfiguration" to get the "GetConnectionString" method with my own connection string. It didn't work. – DanielV Sep 20 '18 at 09:31
  • 34
    This does not appear to work. An alternative is not to mock at all: builder.AddInMemoryCollection(new Dictionary { { "ConnectionStrings:DB", "MyConnection" }, { "MyKey", "MyValue" } }); var config = builder.Build(); – Gracie Dec 10 '18 at 12:59
  • 1
    @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 – Ciarán Bruen Feb 20 '20 at 13:10
  • 1
    Won't work in many cases, like when using `.Get` extension method. – Ahmad Jul 20 '20 at 19:20
13
  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[]

Karan
  • 12,059
  • 3
  • 24
  • 40
2

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");
Chris D
  • 134
  • 1
  • 10