Search code examples
c#configurationasp.net-core-mvcmoqxunit

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();
    }
}

Solution

  • 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 ;)