Как внедрить параметры конфигурации в тестовые классы (ASP.NET Core)?

SmtpConfig содержит мои учетные данные, которые я хочу использовать в тестовом классе. appsettings.development.json

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "SmtpConfig": {
    "credentials": "username:password"
  }
}

Здесь я настраиваю smtpConfig для внедрения в классы (в классах контроллера работает очень хорошо!) Startup.cs

public IConfigurationRoot Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
      services.AddMvc();

      services.Configure<SmtpConfig(
         Configuration.GetSection(nameof(SmtpConfig)
      ));
}

Я хочу получить доступ к учетным данным из appsettings.development.json в тестах, потому что на другом сервере у меня будет другой файл конфигурации.

//important usings
using Microsoft.Extensions.Options;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
    public class SomeControllerAPITest
    {
       private SmtpConfig _smtpConfig;

        public SomeControllerAPITest(IOptions<SmtpConfig> smtpConfig)
        {
            _smtpConfig = smtpConfig.Value;
        }


        [TestMethod]
        public void Post_ReturnsCreatedInstance()
        {
            var credentials = _smtpConfig.credentials;

            //use that credentials
            ...

            //call remote server
            ...
        }
}

Возможно ли это сделать?


person Alex    schedule 05.07.2017    source источник


Ответы (2)


- Создать файл класса в testProject

public static IConfiguration getConfig(){ 
   var config = new ConfigurationBuilder() 
     .SetBasePath("/Users/Project/")
     .AddJsonFile("appsettings.json")  
     .Build(); 
   return config; 
}

    [TestClass]
    public class TestMasterClass
    {
        public static IConfiguration _configuration { get; set; }

        public TestMasterClass()
        {
            _configuration = AnotherClassFile.getConfig();
        }

        [TestMethod]
        public void TestConfigElasticSearch()
        {

            var elasticSearch = _configuration["ElasticSearchConfig:Link01"];
            Assert.IsNotNull(elasticSearch);
        }
    }
person Jonathan Troncoso    schedule 10.07.2018
comment
Этот ответ можно улучшить, объяснив, что делает ваш код для решения заданного вопроса. - person Greg the Incredulous; 10.07.2018

Вы можете использовать ту же функцию привязки Microsoft.Extensions.Configuration для создания идентично заполненного экземпляра IOptions<TConfiguration>. Вот грубый эквивалент того, как мы реализовали это для нашего тестового кода:

public class TestSmtpConfigOptions : IOptions<SmtpConfig> {

    private static Lazy<SmtpConfig> configuration { get; }

    static TestSmtpConfigOptions() {
        configuration = new Lazy<SmtpConfig>(GetConfiguration);
    }

    public SmtpConfig Value {
        get { return configuration.Value; }
    }

    private static SmtpConfig GetConfiguration() {
        var configuration = new SmtpConfig();
        var path = Path.Combine("config", "appsettings.development.json");

        new ConfigurationBuilder()
            .SetBasePath("path/to/base/directory/of/project")
            .AddJsonFile(path, optional: true)
            .Build()
            .GetSection(nameof(SmtpConfig))
            .Bind(configuration);

        return configuration;
    }

}

Затем в вашем приборе вам нужно только создать его экземпляр:

[TestClass]
public class SomeControllerAPITest {

    private SmtpConfig _smtpConfig;

    public SomeControllerAPITest() {
        _smtpConfig = new TestSmtpConfigOptions().Value;
    }


    [TestMethod]
    public void Post_ReturnsCreatedInstance() {
        var credentials = _smtpConfig.credentials;

        //use that credentials
        ...

        //call remote server
        ...
    }
}

Если вы заботитесь о межплатформенных путях и не возражаете против небольшой дополнительной сложности, вот небольшой класс, который мы используем, чтобы получить базовый путь кросс-платформенным способом для нашего средства запуска тестов xUnit. Это означает, что мы используем TestConfiguration.BasePath вместо "path/to/base/directory/of/project" в приведенном выше примере.

internal static class TestConfiguration {

    internal static string BasePath { get; }

    static TestConfiguration() {
        BasePath = Environment.GetEnvironmentVariable("BASE_DIRECTORY");

        if (BasePath == null) {
            BasePath = AppContext.BaseDirectory;

            // cross-platform equivalent of "../../../../../"
            for (var index = 0; index < 5; index++) {
                BasePath = Directory.GetParent(BasePath).FullName;
            }
        }
    }

    internal static string ResolvePath(string relativePath) {
        return Path.Combine(BasePath, relativePath);
    }

}
person Technetium    schedule 30.10.2017