Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock IConfiguration.GetValue

I tried in vain to mock a top-level (not part of any section) configuration value (.NET Core's IConfiguration). For example, neither of these will work (using NSubstitute, but it would be the same with Moq or any mock package I believe):

var config = Substitute.For<IConfiguration>();
config.GetValue<string>(Arg.Any<string>()).Returns("TopLevelValue");
config.GetValue<string>("TopLevelKey").Should().Be("TopLevelValue"); // nope
// non generic overload
config.GetValue(typeof(string), Arg.Any<string>()).Returns("TopLevelValue");
config.GetValue(typeof(string), "TopLevelKey").Should().Be("TopLevelValue"); // nope

In my case, I also need to call GetSection from this same config instance.

like image 780
dudeNumber4 Avatar asked Nov 11 '20 21:11

dudeNumber4


People also ask

Can we mock IConfiguration?

You can Mock GetSection and return your Own IConfigurationSection .

What is IConfiguration C#?

Get<T>(IConfiguration) Attempts to bind the configuration instance to a new instance of type T. If this configuration section has a value, that will be used.

How to get the value of iconfigurationsection using mock?

Create a mock for IConfigurationSection (mockSection) & Setup .Value Property to return your desired config value. 2). Mock .GetSection on Mock<IConfiguration>, and return the above mockSection.Object .GetValue () internally makes use of GetSection (). Show activity on this post. Show activity on this post.

How to mock getsection from getValue<T> method?

} } You can see from the code snippet from above that GetValue<T> uses GetValue which down the line is calling GetSection. Method GetSection is declared in IConfiguration which means you can mock it, and by mocking it you also mock GetValue<T> as it is wrapping GetSection indirectly through GetValue.

What is mocking iconfiguration interface in NET Core?

Mock IConfiguration from net core Mar 1, 2019 1 minute read Problem We use IConfigurationinterface to get access for information of sections and connection strings from our appsettings.json. However, we also need to test our code by mocking this interface with our configurations.

Is it possible to mock a configuration in Python?

Of course the intention is that you read the configuration at the start, pass through a model class and no mocking is required. However, sometimes you’ll find yourself wanting to mock out a particular setting.


Video Answer


5 Answers

You can use an actual Configuration instance with in-memory data.

//Arrange
var inMemorySettings = new Dictionary<string, string> {
    {"TopLevelKey", "TopLevelValue"},
    {"SectionName:SomeKey", "SectionValue"},
    //...populate as needed for the test
};

IConfiguration configuration = new ConfigurationBuilder()
    .AddInMemoryCollection(inMemorySettings)
    .Build();


//...

Now it is a matter of using the configuration as desired to exercise the test

//...

string value = configuration.GetValue<string>("TopLevelKey");

string sectionValue = configuration.GetSection("SectionName").GetValue<string>("SomeKey");

//...

Reference: Memory Configuration Provider

like image 128
Nkosi Avatar answered Oct 24 '22 02:10

Nkosi


I do not have idea about NSubstitute, but this is how we can do in Moq. Aproach is same in either cases.

GetValue<T>() internally makes use of GetSection().

You can Mock GetSection and return your Own IConfigurationSection.

This includes two steps.

1). Create a mock for IConfigurationSection (mockSection) & Setup .Value Property to return your desired config value.

2). Mock .GetSection on Mock< IConfiguration >, and return the above mockSection.Object

Mock<IConfigurationSection> mockSection = new Mock<IConfigurationSection>();
mockSection.Setup(x=>x.Value).Returns("ConfigValue");

Mock<IConfiguration> mockConfig = new Mock<IConfiguration>();
mockConfig.Setup(x=>x.GetSection(It.Is<string>(k=>k=="ConfigKey"))).Returns(mockSection.Object);
like image 33
Shekar Reddy Avatar answered Oct 24 '22 02:10

Shekar Reddy


Mock IConfiguration

Mock<IConfiguration> config = new Mock<IConfiguration>();

SetupGet

config.SetupGet(x => x[It.Is<string>(s => s == "DeviceTelemetryContainer")]).Returns("testConatiner");
config.SetupGet(x => x[It.Is<string>(s => s == "ValidPowerStatus")]).Returns("On");
like image 12
Lokesh Chikkala Avatar answered Oct 24 '22 01:10

Lokesh Chikkala


IConfiguration.GetSection<T> must be mocked indirectly. I don't fully understand why because NSubstitute, if I understand correctly, creates its own implementation of an interface you're mocking on the fly (in memory assembly). But this seems to be the only way it can be done. Including a top-level section along with a regular section.

var config = Substitute.For<IConfiguration>();
var configSection = Substitute.For<IConfigurationSection>();
var configSubSection = Substitute.For<IConfigurationSection>();
configSubSection.Key.Returns("SubsectionKey");
configSubSection.Value.Returns("SubsectionValue");
configSection.GetSection(Arg.Is("SubsectionKey")).Returns(configSubSection);
config.GetSection(Arg.Is("TopLevelSectionName")).Returns(configSection);

var topLevelSection = Substitute.For<IConfigurationSection>();
topLevelSection.Value.Returns("TopLevelValue");
topLevelSection.Key.Returns("TopLevelKey");
config.GetSection(Arg.Is<string>(key => key != "TopLevelSectionName")).Returns(topLevelSection);

// GetValue mocked indirectly.
config.GetValue<string>("TopLevelKey").Should().Be("TopLevelValue");
config.GetSection("TopLevelSectionName").GetSection("SubsectionKey").Value.Should().Be("SubsectionValue");
like image 3
dudeNumber4 Avatar answered Oct 24 '22 01:10

dudeNumber4


I could imagine in some rare scenarios it is needed but, in my humble opinion, most of the time, mocking IConfiguration highlight a code design flaw.

You should rely as much as possible to the option pattern to provide a strongly typed access to a part of your configuration. Also it will ease testing and make your code fail during startup if your application is misconfigured (instead than at runtime when the code reading IConfiguration is executed).

If you really(really) need to mock it then I would advice to not mock it but fake it with an in-memory configuration as explained in @Nkosi's answer

like image 2
asidis Avatar answered Oct 24 '22 03:10

asidis