Как протестировать веб-API ASP.NET, работающий в памяти, с помощью Flurl?

Проблема, которую я пытаюсь решить:

Как протестировать клиентский код, который вызывает REST, вместе с реальным кодом сервера REST (эффективным способом)?

Цели:

  1. Это был бы своего рода интеграционный тест, но быстрый и простой

  2. Это позволит обнаружить e. грамм. ошибка, из-за которой клиент вызывает метод REST с неправильным глаголом (например, PUT, но API принимает POST)

  3. Я считаю слишком сложным проводить интеграционные тесты с развертыванием службы REST, а затем использовать мою библиотеку API для вызова, поэтому я думаю заменить ее модульными/интеграционными тестами в памяти.

  4. Я считаю библиотеку Flurl полезной, поэтому я хотел бы использовать ее в таком тесте.

  5. Вдохновение: https://stackoverflow.com/a/37510032/1453525

Моя идея: я хотел бы провести тесты Flurl Api с реальным ApiController, работающим в памяти (с использованием HttpServer), а не с использованием Flurl HttpTest. Я нашел эту технику здесь: https://stackoverflow.com/a/37510032/1453525 Однако для этого требуется создать сообщение HttpRequest каждый раз и не имеет хорошего API для тестирования. Можно ли запустить код Flurl против реальных тестов ApiController в памяти?


person one_mile_run    schedule 17.07.2017    source источник
comment
Внутренне Flurl использует HttpClient, поэтому вы все равно можете настроить его на использование того, который был сгенерирован в памяти HttpServer.   -  person Nkosi    schedule 17.07.2017


Ответы (1)


Я не проверял это, но я считаю, что вы сможете использовать Flurl с хостингом в памяти, создав собственный HttpClientFactory и переопределив CreateMessageHandler:

public class TestingClientFactory : DefaultHttpClientFactory
{
    public overrride HttpMessageHandler CreateMessageHandler()
    {
        var config = new HttpConfiguration();
        //configure web api
        WebApiConfig.Register(config);

        return new HttpServer(config);
    }
}

В своей тестовой сборке зарегистрируйте это глобально, в идеале запуская только один раз при настройке тестового устройства:

FlurlHttp.Configure(settings => settings.HttpClientFactory = new TestingClientFactory());

Теперь каждый раз, когда Flurl нужно создать новый HttpClient в ваших тестах, он будет использовать сервер в памяти.

person Todd Menier    schedule 18.07.2017
comment
Основываясь на моем обзоре исходного репо, это должно работать. В зависимости от того, где определены контроллеры, им может потребоваться вызвать WebApiConfig.Register из уровня представления и применить его к config. - person Nkosi; 18.07.2017
comment
@Todd Menier: я устанавливаю этот код, однако это не отличается от TestingClientFactory. CreateMessageHandler() не выполняется (не попадает в отладчик). Понятия не имею почему. Я использую HttpTest(). - person one_mile_run; 31.07.2017
comment
@one_mile_run Как я уже говорил, не используйте HttpTest. Это специально для подделки всех HTTP-вызовов, сделанных с помощью Flurl, а это не то, что вы хотите делать. Вы хотите совершать реальные вызовы на ваш HttpServer в памяти. CreateMessageHandler не попадает, потому что существует HttpTest заставляет его пропустить. - person Todd Menier; 31.07.2017
comment
@ToddMenier: Хорошо, теперь я понимаю, почему мне не следует использовать HttpTest. Я предполагал, что буду использовать его Assert API, но это не имеет смысла, поскольку звонки не подделываются. После пары попыток у меня заработал последний тест. Мне пришлось настроить TestingClientFactory, чтобы зарегистрировать преобразователь DI и настроить значения конфигурации. Тем не менее, я не уверен, что FlurlHttp.Configure() подойдет для параллельных тестов, потому что это глобальная конфигурация. Это дизайнерское решение? - person one_mile_run; 02.08.2017
comment
@ToddMenier: Также я получаю предупреждение при запуске такого теста с использованием NUnit3: System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain. This can happen if the test(s) started a thread but did not stop it. Make sure that all the threads started by the test(s) are stopped before completion. Я думаю, что это еще одна проблема для отдельного исследования, поскольку она может быть связана с самим NUnit или моим собственным кодом. - person one_mile_run; 02.08.2017
comment
@one_mile_run FlurlHttp.Configure следует вызывать один раз при запуске приложения. Для набора тестов NUnit сделайте это здесь. - person Todd Menier; 02.08.2017