14

I have class AbClass that get with asp.net core built-in DI instance of IOptionsSnapshot<AbOptions> (dynamic configuration). now I want to test this class.

I'm trying to instantiate AbClass class in test class, but I have no idea how can I instantiate an instance of IOptionsSnapshot<AbOptions> to inject into the constructor of AbClass.

I tried use Mock<IOptionsSnapshot<AbOptions>>.Object, but I need to set some values to this instance, since in AbClass the code is using this values (var x = _options.cc.D1).

so I have a code like

var builder = new ConfigurationBuilder();
builder.AddInMemoryCollection(new Dictionary<string, string>
{
    ["Ab:cc:D1"] = "https://",
    ["Ab:cc:D2"] = "123145854170887"
});
var config = builder.Build();
var options = new AbOptions();
config.GetSection("Ab").Bind(options);

but I dont know how to link this Options and the IOptionsSnapshot mock.

AbClass:

public class AbClass {
    private readonly AbOptions _options;

    public AbClass(IOptionsSnapshot<AbOptions> options) {
        _options = options.Value;    
    }
    private void x(){var t = _options.cc.D1}
}

my test instantiate this class:

var service = new AbClass(new Mock???)

and need to test a method in AbClass that call x(), but it throw ArgumentNullException when it on _options.cc.D1

Nkosi
  • 191,971
  • 29
  • 311
  • 378
arielorvits
  • 4,013
  • 4
  • 29
  • 52
  • 4
    Good question! With `IOptions` there's a static `Create` method on the `Options` class but there's no equivalent jumping out at me for `IOptionsSnapshot`. Curious what the answer is. –  Dec 12 '16 at 23:53

2 Answers2

16

You should be able to mock up the interface and create an instance of the options class for the test. As I am unaware of the nested classes for the options class I am making a broad assumption.

Documentation: IOptionsSnapshot

//Arrange
//Instantiate options and nested classes
//making assumptions here about nested types
var options = new AbOptions(){
    cc = new cc {
        D1 = "https://",
        D2 = "123145854170887"
    }
};
var mock = new Mock<IOptionsSnapshot<AbOptions>>();
mock.Setup(m => m.Value).Returns(options);

var service = new AbClass(mock.Object);

Access to the nested values should now return proper values instead of NRE

Nkosi
  • 191,971
  • 29
  • 311
  • 378
4

A generic way:

    public static IOptionsSnapshot<T> CreateIOptionSnapshotMock<T>(T value) where T : class, new()
    {
        var mock = new Mock<IOptionsSnapshot<T>>();
        mock.Setup(m => m.Value).Returns(value);
        return mock.Object;
    }

usage:

var mock = CreateIOptionSnapshotMock(new AbOptions(){
    cc = new cc {
        D1 = "https://",
        D2 = "123145854170887"
    }
});
Bastiflew
  • 976
  • 2
  • 15
  • 28