0
votes

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();
    }
}
2
Is it appSettings.json or web.config ? Sample file would be helpful. - dotnetstep
It's .net core so app settings.json - plasteezy
@plasteezy Did any of the suggested solution work for you? - Peter Csala

2 Answers

1
votes

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

0
votes

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