Это связано с первоначальной проблемой дизайна.
Класс Config
тесно связан с проблемами реализации
Environment.GetEnvironmentVariable
, которые отсутствуют при тестировании по отдельности и вызывают исключения.
Как точно указано в комментарии, вы должны были воспользоваться модулем конфигурации и зарегистрировать свою конфигурацию вместо того, чтобы тесно связывать ее с классом Environment
.
Ссылка: Настройка простых параметров с делегатом
builder.Services.Configure<Config>(options => {
options.Key1 = Environment.GetEnvironmentVariable("abc");
options.Key2 = Environment.GetEnvironmentVariable("xyz");
});
Теперь это означает, что класс можно упростить до базовых c POCO
public class Config {
public string Key1 { get; set; }
public string Key2 { get; set; }
}
И явно ввести IOptions<Config>
в функцию субъекта.
private readonly Config config;
//ctor
public MyFunction(IOptions<Config> options) {
config = options.Value;
//...
}
Если вы, однако, не хотите тесно связывать функцию с IOptions<>
интерфейсом, дополнительная регистрация, аналогичная той, что была первоначально сделана, может обойти это. Зарегистрируйте свой тип и разрешите параметры для извлечения его значения в делегате фабрики.
builder.Services.Configure<Config>(options => {
options.Key1 = Environment.GetEnvironmentVariable("abc");
options.Key2 = Environment.GetEnvironmentVariable("xyz");
});
builder.Services.AddSingleton((s) => {
return s.GetRequiredService<IOptions<Config>>().Value;
});
Это позволит классу Config
явным образом вводиться в функцию субъекта без необходимости в интерфейсе, где простой POCO сделает.
//ctor
public MyFunction(Config config) {
//...
}
, что позволит протестировать функцию изолированно без нежелательных побочных эффектов от проблем реализации
//Arrange
var mockConfiguration = new Config() {
Key1 = "value"
};
var subject = new MyFunction(mockConfiguration);
//...