Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Unit Test Method Calling IConfiguration.Get<T> extension

I have this very simple method that I need to unit test.

public static class ValidationExtensions
{
    public static T GetValid<T>(this IConfiguration configuration)
    {
        var obj = configuration.Get<T>();
        Validator.ValidateObject(obj, new ValidationContext(obj), true);
        return obj;
    }
}

The problem is that configuration.Get<T> is a static extension method and doesn't belong to IConfiguration. I can't change the implementation of that static method.

I'm thinking, perhaps the simplest way is to create a Memory Configuration Provider? But I don't know if I can create one without binding it to a web host.

like image 954
Etienne Charland Avatar asked Mar 13 '19 04:03

Etienne Charland


People also ask

Can we mock IConfiguration?

You can see from the code snippet from above that GetValue<T> uses GetValue which down the line is calling GetSection. Method GetSection is declared in IConfiguration which means you can mock it, and by mocking it you also mock GetValue<T> as it is wrapping GetSection indirectly through GetValue.

What is the use of IConfiguration?

The IConfiguration is an interface for . Net Core 2.0. The IConfiguration interface need to be injected as dependency in the Controller and then later used throughout the Controller. The IConfiguration interface is used to read Settings and Connection Strings from AppSettings.


1 Answers

The configuration module is independent of web host related features.

You should be able to create an in memory configuration to test against without the need to bind it to a web host.

Review the following example test

public class TestConfig {
    [Required]
    public string SomeKey { get; set; }
    [Required] //<--NOTE THIS
    public string SomeOtherKey { get; set; }
}

//...

[Fact]
public void Should_Fail_Validation_For_Required_Key() {
    //Arrange
    var inMemorySettings = new Dictionary<string, string>
    {
        {"Email:SomeKey", "value1"},
        //{"Email:SomeOtherKey", "value2"}, //Purposely omitted for required failure
        //...populate as needed for the test
    };

    IConfiguration configuration = new ConfigurationBuilder()
        .AddInMemoryCollection(inMemorySettings)
        .Build();

    //Act
    Action act = () => configuration.GetSection("Email").GetValid<TestConfig>();

    //Assert
    ValidationException exception = Assert.Throws<ValidationException>(act);
    //...other assertions of validation results within exception object
}

This in my opinion would be coming close to an integration test, but ideally you are just using framework dependent features in order to isolate the testing of the extension method.

like image 109
Nkosi Avatar answered Nov 14 '22 13:11

Nkosi