Test IOptionsMonitor<T> in ASP.NET Core

mpetrinidev

Mauro Petrini 👨‍💻

Posted on November 23, 2019

Test IOptionsMonitor<T> in ASP.NET Core

Welcome! Spanish articles on LinkedIn. You can follow me on Twitter for news.


Imagine you are using the options pattern in .NET Core to set up some configuration in your application, and you need to test it. Through this example, you will learn how to test the options you have configured.

Let's begin

Option Class

An options class must be non-abstract with a public parameterless constructor. I create a class called GmailSmtpOptions to simulate the configuration that we need for a Gmail email service.

    public class GmailSmtpOptions
    {
        public string Server { get; set; }
        public bool UseAuthentication { get; set; }
        public bool UseSecureConnection { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public int Port { get; set; }    
    }

Service collection extension

I create a simple service collection extension to add GmailSmtpOptions to the container.

I'm configuring the options passing a delegate in the AddCustomOptions and use the Configure method of the container.

    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddCustomOptions(this IServiceCollection serviceCollection, Action<GmailSmtpOptions> gmailSmtpOptions)
        {
            serviceCollection.Configure(gmailSmtpOptions);
            return serviceCollection;
        }
    }

xUnit class for test

Arrange

I set up the test with some information about the SMTP server. Also, I use the service collection to call the AddCustomOptions extension method that we previously created.

    var server = "smtp.gmail.com";
    var useAuth = true;
    var useSecCon = true;
    var username = "username";
    var password = "password";
    var port = 465;

    var serviceCollection = new ServiceCollection();
    serviceCollection.AddCustomOptions(gmail =>
    {
        gmail.Server = server;
        gmail.UseAuthentication = useAuth;
        gmail.UseSecureConnection = useSecCon;
        gmail.Username = username;
        gmail.Password = password;
        gmail.Port = port;
    });

Act

Then, I call the BuildServiceProvider method to create the provider containing services from the provided IServiceCollection and get the IOptionsMonitor<T> service.

    var builder = serviceCollection.BuildServiceProvider();
    var optionsMonitor = builder.GetService<IOptionsMonitor<GmailSmtpOptions>>();

Assert

We get the IOptionsMonitor, and now we need to compare the values configured previously. We use the CurrentValue property to get the current TOptions instance (GmailSmtpOptions).

    //Assert 1
    optionsMonitor.Should().NotBeNull();
    optionsMonitor.CurrentValue.Should().NotBeNull().And.BeOfType<GmailSmtpOptions>();

    var gmailOptions = optionsMonitor.CurrentValue;

    //Assert 2
    gmailOptions.Should().NotBeNull();

    //Assert 3
    gmailOptions.Server.Should().NotBeNullOrEmpty().And.Be(server);
    gmailOptions.UseAuthentication.Should().Be(useAuth);
    gmailOptions.UseSecureConnection.Should().Be(useSecCon);
    gmailOptions.Username.Should().NotBeNullOrEmpty().And.Be(username);
    gmailOptions.Password.Should().NotBeNullOrEmpty().And.Be(password);
    gmailOptions.Port.Should().Be(port);

That's all!

Complete code

    public class ServiceCollectionExtensionsTest
    {
        [Fact]
        public void AddCustomOptions_NoConfigureOptions_ConfigureOptionsOk()
        {
            //Arrange
            var server = "smtp.gmail.com";
            var useAuth = true;
            var useSecCon = true;
            var username = "username";
            var password = "password";
            var port = 465;

            var serviceCollection = new ServiceCollection();
            serviceCollection.AddCustomOptions(gmail =>
            {
                gmail.Server = server;
                gmail.UseAuthentication = useAuth;
                gmail.UseSecureConnection = useSecCon;
                gmail.Username = username;
                gmail.Password = password;
                gmail.Port = port;
            });

            //Act
            var builder = serviceCollection.BuildServiceProvider();
            var optionsMonitor = builder.GetService<IOptionsMonitor<GmailSmtpOptions>>();

            //Assert 1
            optionsMonitor.Should().NotBeNull();
            optionsMonitor.CurrentValue.Should().NotBeNull().And.BeOfType<GmailSmtpOptions>();

            var gmailOptions = optionsMonitor.CurrentValue;

            //Assert 2
            gmailOptions.Should().NotBeNull();

            //Assert 3
            gmailOptions.Server.Should().NotBeNullOrEmpty().And.Be(server);
            gmailOptions.UseAuthentication.Should().Be(useAuth);
            gmailOptions.UseSecureConnection.Should().Be(useSecCon);
            gmailOptions.Username.Should().NotBeNullOrEmpty().And.Be(username);
            gmailOptions.Password.Should().NotBeNullOrEmpty().And.Be(password);
            gmailOptions.Port.Should().Be(port);
        }
    }

I'm using the following packages in the test project.

    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
    <PackageReference Include="xunit" Version="2.4.0" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
    <PackageReference Include="coverlet.collector" Version="1.0.1" />
💖 💪 🙅 🚩
mpetrinidev
Mauro Petrini 👨‍💻

Posted on November 23, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related