简体   繁体   中英

How do I mock IConfiguration with Moq?

How do I mock code like this in my unit test. I'm using xUnit and Moq in asp.net core 5. I'm new to xUnit and Moq.

var url = configuration.GetSection("AppSettings").GetSection("SmsApi").Value;

The configuration object is already injected into the constructor.

This is what I currently have in my unit test class

public class UtilityTests
{
    private readonly Utility sut;

    public UtilityTests()
    {
        var mockConfig = new Mock<IConfiguration>();
        var mockConfigSection = new Mock<IConfigurationSection>();
        //mockConfigSection.Setup(x => x.Path).Returns("AppSettings");
        mockConfigSection.Setup(x => x.Key).Returns("SmsApi");
        mockConfigSection.Setup(x => x.Value).Returns("http://example.com");
        
        mockConfig.Setup(x => x.GetSection("AppSettings")).Returns(mockConfigSection.Object);
        
        sut = new Utility(mockConfig.Object);
    }

    [Fact]
    public void SendSmsShdReturnTrue()
    {
        var fixture = new Fixture();
        
        var result = sut.SendSms(fixture.Create<string>(), fixture.Create<string>());
        result.Should().BeTrue();
    }
}

Alternative approach tp introduce a class to represent section of the configuration, then use IOptions interface to inject it to the constructor.

Your tests then become simple to configure without mocking, just create an instance and pass it to the constructor.

Something like below:

class SmsApiSettings
{
    public string Url { get; set; }
}

Register during startup

services.Configure<SmsApiSettings>(Configuration.GetSection("SmsApi"));

Constructor

public class ClassUnderTest
{
    private readonly SmsApiSettings _smsApiSettings;

    public ClassUnderTest(IOptions<> smsOptions)
    {
        _smsApiSettings = smsOptions.Value;
    }
}

Tests

var settings = new SmsApiSettings { Url = "http://dummy.com" };
var options = Options.Create(settings);

var sut = new ClassUnderTest(options);

Enjoy happy life without mocks;)

The truth is that the IConfiguration should not be mocked. Instead it should be built .

via dictionary

Data

var configForSmsApi = new Dictionary<string, string>
{
    {"AppSettings:SmsApi", "http://example.com"},
};

Usage

var configuration = new ConfigurationBuilder()
    .AddInMemoryCollection(configForSmsApi)
    .Build();

via json file

Data

{
  "AppSettings": {
    "SmsApi": "http://example.com"
  }
}

Usage

var configuration = new ConfigurationBuilder()
    .AddJsonFile("smsapi.json", optional: false)
    .Build();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM