Search code examples
c#unit-testingasp.net-coreautomocking

IConfiguration keeps getting null value when mocking


May I enquire if I am mocking my IConfiguration correctly as I keep get a null error. I am trying to mock my controller where it reads the appsettings.json.

ControllerOne.cs

 private readonly IConfiguration _configuration;
 public Controller(IConfiguration configuration)
 {
     _configuration = configuration;
 }

 [HttpPost("upload")]
 public async Task<IActionResult> UploadFile([FromForm(Name = "files")] List<IFormFile> files, CancellationToken cancellationToken = default)
 {
      string directory = _configuration.GetValue<string>("ShippingService:ServerDirectory");
      string subDirectory = _configuration.GetValue<string>("ShippingService:UploadRateSubDirectory");
 }

ControllerTest.cs

public class ControllerTest: ControllerTestsBase<ControllerOne>
{

   [Fact]
   public void TestOne()
   {
       IFormFile file = new FormFile(new MemoryStream(Encoding.UTF8.GetBytes("This is a dummy file")), 0, 0, "Data", "dummy.txt");
       List<IFormFile> formFiles = new List<IFormFile>();
       formFiles.Add(file);
       //when
       await Controller.UploadFile(formFiles, default);
   }
}

ControllerTestsBase.cs

 public abstract class ControllerTestsBase<T>
    where T : ApiControllerBase
{
    protected readonly T Controller;
    protected readonly AutoMocker Mocker;

    protected ControllerTestsBase()
    {
        Mocker = new AutoMocker();

        var httpResponseMock = Mocker.GetMock<HttpResponse>();
        httpResponseMock.Setup(mock => mock.Headers).Returns(new HeaderDictionary());

        var httpRequestMock = Mocker.GetMock<HttpRequest>();

        var httpContextMock = Mocker.GetMock<HttpContext>();
        httpContextMock.Setup(mock => mock.Response).Returns(httpResponseMock.Object);
        httpContextMock.Setup(mock => mock.Request).Returns(httpRequestMock.Object);

        var fakeValues = new Dictionary<string, string>
        {
            {"ShippingService:ServerDirectory", "abc"},
            {"ShippingService:UploadRateSubDirectory", "test.com"}
        };

        IConfiguration config = new ConfigurationBuilder()
            .AddInMemoryCollection(fakeValues)
            .Build();

        Controller = Mocker.CreateInstance<T>();
        Controller.ControllerContext.HttpContext = httpContextMock.Object;
    }
}

When I debug and trace to the Controller.cs methodOne, the _configuration keeps prompted null error.

  • Apologies for the snippet of code, I have updated the code again.
  • I have also realized that my previous post here c# Mock IConfiguration keeps get null is being closed as I have previously posted something that couldn't compile.

Solution

  • The docs state:

    If you have a special instance that you need to use, you can register it with .Use(...). This is very similar to registrations in a regular IoC container (i.e. For().Use(x) in StructureMap).

    Therefore I expect this would work:

    IConfiguration config = new ConfigurationBuilder()
        .AddInMemoryCollection(fakeValues)
        .Build();
    
    Mocker.Use<IConfiguration>(config);
    
    Controller = Mocker.CreateInstance<T>();
    Controller.ControllerContext.HttpContext = httpContextMock.Object;