Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ServiceCollection returns null for IOptions even though GetSection is working

Tags:

.net

.net-core

I'm having trouble manually constructing a IServiceProvider that will allow my unit tests to use it to pull in shared test configuration using GetService<IOptions<MyOptions>>

I created some unit tests to illustrate my problems, also the repo for this can be found here if it's useful in answering the question.

The JSON

{
  "Test": {
    "ItemOne":  "yes"
  }
}

The Options Class

public class TestOptions
{
    public string ItemOne { get; set; }
}

The Tests

Out of these tests ConfigureWithBindMethod and ConfigureWithBindMethod both fail, where SectionIsAvailable passes. So the section is being consumed as expected from the JSON file as far as I can tell.

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void ConfigureWithoutBindMethod()
    {
        var collection = new ServiceCollection();

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

        collection.Configure<TestOptions>(config.GetSection("Test"));

        var services = collection.BuildServiceProvider();

        var options = services.GetService<IOptions<TestOptions>>();

        Assert.IsNotNull(options);
    }

    [TestMethod]
    public void ConfigureWithBindMethod()
    {
        var collection = new ServiceCollection();

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

        collection.Configure<TestOptions>(o => config.GetSection("Test").Bind(o));

        var services = collection.BuildServiceProvider();

        var options = services.GetService<IOptions<TestOptions>>();

        Assert.IsNotNull(options);
    }

    [TestMethod]
    public void SectionIsAvailable()
    {
        var collection = new ServiceCollection();

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

        var section = config.GetSection("Test");
        Assert.IsNotNull(section);
        Assert.AreEqual("yes", section["ItemOne"]);
    }
}

Possibly useful to point out

When calling config.GetSection("Test") in the immediate window, I get this value

{Microsoft.Extensions.Configuration.ConfigurationSection}
    Key: "Test"
    Path: "Test"
    Value: null

At face value I'd have assumed Value should not be null, which is leading me to think I may be missing something obvious here, so if anyone can spot what I'm doing wrong that'd be genius.

Thanks!

like image 335
Chris Avatar asked Sep 03 '17 03:09

Chris


1 Answers

To use options in your service collection, you need to add the service required for using options collection.AddOptions();

This should do the trick:

[TestMethod]
public void ConfigureWithoutBindMethod()
{
    var collection = new ServiceCollection();
    collection.AddOptions();

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

    collection.Configure<TestOptions>(config.GetSection("Test"));

    var services = collection.BuildServiceProvider();

    var options = services.GetService<IOptions<TestOptions>>();

    Assert.IsNotNull(options);
}
like image 130
kloarubeek Avatar answered Nov 13 '22 16:11

kloarubeek