Получить конфигурацию в модульном тесте - PullRequest
1 голос
/ 26 мая 2020

Я не могу понять, как получить некоторую конфигурацию, которую я использую, следуя шаблону IOptions.

Служба, которую я хочу протестировать, является следующей:

        private readonly Dictionary<ErrorType, ErrorObject> _errors;

        public UserService(
            ...(Many services)...
            IOptions<Dictionary<ErrorType, ErrorObject>> errors)
        {
            ...
            _errors = errors.Value;
        }

Где ErrorType - это Enum, а ErrorObject - объект с форматом ошибок, которые есть в моих настройках приложения. json. Вот он:

{
  "Errors": {
    "UserNotFound": {
      "ErrorCode": 101,
      "Message": "User not found"
    },
    "WrongPassword": {
      "ErrorCode": 102,
      "Message": "Wrong password"
    }
  }
}

Итак, это работает отлично, но теперь моя проблема в том, что я не знаю, как создать его экземпляр, издеваться над ним или внедрить в свой тестовый класс, поскольку даже я вводя его, я не могу разрешить его в таком классе, и я всегда получаю ноль. Я ввел его в тестовом приспособлении (так же, как и в моем реальном модуле инъекции):

serviceCollection.Configure<Dictionary<BusinessErrorType, BusinessErrorObject>>(x => Configuration.GetSection("Errors").Bind(x));

Мне нужно правильно ввести IConfiguration со всеми ошибками, я просто не могу создать необходимые Словарь для конструктора.

Здесь я без проблем получаю ошибки:

IConfiguration Configuration = ioCModule.ServiceProvider.GetRequiredService<IConfiguration>();
            var errorsConfig = Configuration.GetSection("Errors");

И теперь мне нужно выяснить, что поместить в это объявление:

var _options = Options.Create<Dictionary<BusinessErrorType, BusinessErrorObject>>();

1 Ответ

3 голосов
/ 26 мая 2020

Я ввел его вот так в тестовую оснастку (так же, как в моем реальном модуле внедрения):

Вы пробовали ввести словарь, тогда как ваш класс ожидает получения Options. Попробуйте зарегистрировать и ввести параметры, и, скорее всего, это удастся.

И теперь я должен выяснить, что поместить в это объявление:

Options объект - это просто Держатель для какой-то готовой ценности, или ничего. Вы должны создать объект Options, либо присвоив ему значение, либо ничего не дав ему (и получив в итоге пустой объект параметров). Если вы используете Options.Create<Dict>() без каких-либо параметров, вы создаете пустой объект, и все. Просто создайте словарь перед этим и передайте его в Options facotry.

var dict = new Dictionary<BusinessErrorType, BusinessErrorObject>();
dict.Add("UserNotFound", new BusinessErrorObject(....));
dict.Add("WrongPassword", new BusinessErrorObject(....));

var _options = Options.Create<Dictionary<BusinessErrorType, BusinessErrorObject>>(dict);
// now you have it: _options with some data inside

Если вы рассчитываете на использование Bind () с Options - я сомневаюсь, что он будет работать именно так, поскольку Bind используется для заполнения в структурах данных с конфигурацией, считанной из файла настроек, а Options - это просто оболочка, что-то вроде "Nullable <>", она существует только для передачи информации ... Однако я полагаю, вы могли бы сначала создать словарь, а затем заполнить его конфигурацией (т.е. Bind), затем оберните только что заполненный словарь с помощью Options <>, а затем зарегистрируйте этот объект Options в Io C, чтобы ваш UserService мог получить его конфигурацию. Однако я не уверен на 100%, что Bind достаточно умен, чтобы заполнять c словарей. Вам нужно будет проверить это самостоятельно, к сожалению, у меня нет под рукой проекта aspnetcore, чтобы поиграть с

EDIT / Sidenote:

Я немного удивлен, что вы строите / настройка всего Io C в UNIT TEST . При создании модульного теста вы хотите как можно больше вырезать / имитировать зависимости. Это означает, что нет Io C, что может привести к другому набору проблем / сбоев / и т.д. c в тесте.

Я имею в виду, что я ожидаю, что ваш Unit Test будет выглядеть так:

[Test]
public void FoobarizingTheBaz()
{
    var mock1 = ....;
    var mock2 = ....;
    var mock3 = ....;
    var ... = ....;
    var mockN = ....;

    var dict = new Dictionary<....>();
    dict.Add(....);
    dict.Add(....);
    var mockOptions = Options.Create<...>(dict);

    var tested = new UserService(
        mock1, mock2, mock3, ... mockN, mockOptions
    );

    var result = tested.FoobarizeTheBaz();

    // assert...
}

Это модульный тест. Создается только проверенный объект, остальное - имитация, и вы предоставляете только то, что абсолютно необходимо. Конечно, мне пришлось написать чертовски много setup / mocks / et c вместо того, чтобы полагаться на Io C, чтобы автоматически их материализовать, но как только макеты написаны, вы можете перенести их в какой-нибудь общий код, протестировать class init, fixture, et c и использовать их повторно.

То есть, никаких настроек приложения. json. Нет IConfiguration. Нет Io C, et c.

Если вместо этого вы хотите проверить, сколько компонентов взаимодействуют друг с другом, то это больше похоже на интеграционный тест. В этом случае вы можете захотеть увидеть эту статью , которая касается использования пользовательских настроек приложения. json и IOptions в настройке интеграционного теста. Однако помните, что «интеграционные тесты» в aspnetcore обычно означают тестирование того, как ваша служба реагирует на запросы, и проверку ответов, поэтому вы увидите это в этой статье. Тем не менее, часть об IOptions должна быть полезной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...