6

Using this answer to mock the IConfiguration methods from an ASP.NET Core app.

I need to mock an IConfigurationSection to return a string array.

My configuration class looks like this:

public class LoggingConfiguration
{
    public string ApplicationName { get; set; }
    public string[] Loggers { get; set; }
}

appsettings.json

{
    "Logging": {
        "LoggingConfiguration": {
              "ApplicationName": "Some app",
              "Loggers":  [ "DiskLogger", "MemoryLogger"],
              "DiskLogger": {
                  "SomeSettingOne" : "setting",
                  "SomeSettingTwo" : "setting",
               },
              "MemoryLogger": {
                  "AnotherSetting": "...",
               }
       }
}

In setting up the mocks - I have two problems.

  1. I can't figure out how to mock an IConfigurationSection that would return string[] (loggers)
  2. I am getting an exception when I try to setup the GetChildren() method on the LoggingSectionMock
public void Setup()
{
    var applicationNameConfigurationSectionMock = new Mock<IConfigurationSection>();
    applicationNameConfigurationSectionMock.Setup(m => m.Value).Returns(TestingApplicationName);

    var loggerNamesConfigurationSectionMock = new Mock<IConfigurationSection>();
    loggerNamesConfigurationSectionMock.Setup(m => m.GetChildren()).Returns(GetLoggerNamesSection);

    //Throwing Method Not Found exception
    LoggingSectionMock.Setup(m => m.GetChildren()).Returns(new List<IConfigurationSection>
        {applicationNameConfigurationSectionMock.Object, loggerNamesConfigurationSectionMock.Object});

    ConfigurationMock.Setup(m => m.GetSection($"{Logging}:{LoggingConfiguration}"))
        .Returns(() => LoggingSectionMock.Object);
}

private IEnumerable<IConfigurationSection> GetLoggerNamesSection()
{
    var loggerNamesConfigurationSections = new List<IConfigurationSection>();
    LoggerNames.ToList().ForEach(loggerName =>
    {
        var configSectionMock = new Mock<IConfigurationSection>();
        configSectionMock.Setup(m => m.Value).Returns(loggerName);
        loggerNamesConfigurationSections.Add(configSectionMock.Object);
    });
    return loggerNamesConfigurationSections;
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
JDBennett
  • 1,323
  • 17
  • 45
  • 1
    Build an actual IConfiguration using in memory data. Way too much effort to try and mock all that. – Nkosi Nov 03 '20 at 03:49
  • 1
    Show what you are **actually** trying to test. This might be an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – Nkosi Nov 03 '20 at 03:51

1 Answers1

10

As an alternative you can take advantage of ConfigurationBuilder's AddInMemoryCollection:

Reference Memory configuration provider

Setup

IConfiguration configRoot = new ConfigurationBuilder()
    .AddInMemoryCollection(new Dictionary<string, string>
    {
        { "ApplicationName", "App" }, 
        { "Loggers:0", "1" },
        { "Loggers:1", "2" },
        { "Loggers:2", "3" }
    })
    .Build();

Usage

LoggingConfiguration config = configRoot.Get<LoggingConfiguration>();
Nkosi
  • 235,767
  • 35
  • 427
  • 472
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
  • 1
    Yep. This is exactly what I was referring to. Good answer. – Nkosi Nov 03 '20 at 11:39
  • I like this approach - but my appsettings.json is more complicated. I have updated my question to show the appsettings.json structure. I Need to get the "LoggingConfiguration" section of the file. – JDBennett Nov 03 '20 at 13:30
  • I think I found it. https://stackoverflow.com/questions/37825107/net-core-use-configuration-to-bind-to-options-with-array. – JDBennett Nov 03 '20 at 13:41