How to mock IConfiguration.GetValue
Solution 1
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
Solution 2
I do not have idea about NSubstitute, but this is how we can do in Moq. Aproach is same in either cases.
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);
.GetValue() internally makes use of GetSection().
Solution 3
Mock IConfiguration
Mock config = new Mock();
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");
Solution 4
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

dudeNumber4
Long time C# developer. Pretty heavy TSQL developer as well. Some front end too.
Updated on November 14, 2021Comments
-
dudeNumber4 over 1 year
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. -
Tejashree about 2 yearsI tried to set values for two keys in IConfiguration using two different mockSection objects. Still the value of the first key was overridden by the second value and the value of other key was 0. How to solve this problem?
-
Shekar Reddy about 2 yearsMake sure you use the right expression in k=>k=="configkey" istead of .it.isany.
-
Tejashree about 2 yearsThat's how I wrote:
mockConfig.Setup(x => x.SetSection(It.Is<string>(k => k == "Key1"))).Returns(mocksection1.object); mockConfig.Setup(x => x.SetSection(It.Is<string>(k => k == "Key2"))).Returns(mocksection2.object);
-
Shekar Reddy about 2 yearsSetSection or GetSection?
-
jhoepken almost 2 yearsWelcome to Stackoverflow. Can you please elaborate on your answer, to add some context?
-
Tony Mathew almost 2 yearsI should have hit this post hours earlier, NSubstitute while returning nothing on IConfiguration.GetValue<string>, it breaks on GetValue<bool> with an InvalidOperationException: 'Failed to convert configuration value at '' to type 'System.Boolean'.' although the return value is specified correctly.
-
AaBa over 1 yearThis works well, only change I did here was to use constants i.e.
config.SetupGet(x => x[Constants.SOME_KEY]).Returns("testConatiner");
Tx! -
Regianni about 1 yearSpot on - thanks
-
Ashu about 1 yearfor me mockSection.Setup(x=>x.Value).Returns("ConfigValue"); is throwing null object reference exception
-
Shekar Reddy about 1 yeardid you initialize mockSection
-
Diri Jianwei Guo 11 months// example about how to configure a array setting. var inMemorySettings = new Dictionary<string, string> { {"SomeArrayKey:0", "value0"}, {"SomeArrayKey:1", "value1"}, {"SomeArrayKey:2", "value2"} };