Подтвердить что ты не робот

Можно ли тестировать файлы в ASP.NET WebAPI?

Я работаю над проектом, который использует новый ASPAP WebAPI. Моя текущая задача - принять загруженный файл. До сих пор я использовал TDD для извлечения кода WebAPI, но я ударил стену с загрузкой. В настоящее время я следую рекомендациям, изложенным в http://www.asp.net/web-api/overview/working-with-http/sending-html-form-data,-part-2, но, похоже, нет никакого способа выгнать это из unit test. Чтобы получить данные о файле и форме, я должен использовать MultipartFormDataStreamProvider, который невозможно высмеять и/или переопределить. Не удалось отказаться от моего подхода TDD, что я могу сделать?

Вот код из примера:

public Task<HttpResponseMessage> PostFormData()
{
    // Check if the request contains multipart/form-data.
    if (!Request.Content.IsMimeMultipartContent())
    {
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    }

    string root = HttpContext.Current.Server.MapPath("~/App_Data");
    var provider = new MultipartFormDataStreamProvider(root);

    // Read the form data and return an async task.
    var task = Request.Content.ReadAsMultipartAsync(provider).
        ContinueWith<HttpResponseMessage>(t =>
        {
            if (t.IsFaulted || t.IsCanceled)
            {
                Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
            }

            // This illustrates how to get the file names.
            foreach (MultipartFileData file in provider.FileData)
            {
                Trace.WriteLine(file.Headers.ContentDisposition.FileName);
                Trace.WriteLine("Server file path: " + file.LocalFileName);
            }
            return Request.CreateResponse(HttpStatusCode.OK);
        });

    return task;
}

Первая проблема заключается в этой строке:

var provider = new MultipartFormDataStreamProvider(root);

Для начала, до unit test этого кода, мне нужно иметь возможность ввести такого провайдера. Это слишком сложно в этом простом вызове конструктора, чтобы "обновить его" в строке. Должен быть другой путь. (Если нет, произойдет сбой WebAPI)

4b9b3361

Ответ 1

Ответ "нет". ASP.NET - это основанная на наследовании структура. Если вы пытаетесь написать композиционные приложения, вы в какой-то момент найдете трение и дорожные блоки. Время переключиться на что-то вроде Nancy.

Ответ 2

Если вы используете возможность самостоятельного хостинга, вы можете написать unit test, который:

  • Запускает контроллеры (и другие форматы/фильтры/и т.д.).
  • Использует HttpClient (или лично, я бы использовал RestSharp), чтобы отправить файл на этот контроллер (с помощью RestSharp вы можете использовать AddFile, чтобы сделать это)
  • Проверяет входной поток, но вы хотите (например, переопределяя провайдера или просто проверяя значение, которое передается тестовому контроллеру или что-то в этом роде)

Ответ 3

Я отвлек оболочку провайдера, чтобы я мог издеваться над этими движущимися частями, что-то вроде

    public interface IMultiPartFormDataStreamProviderWrapper : IDependency
    {
        string LocalFileName { get; }
        MultipartFormDataStreamProvider Provider { get; }
    }

    public class MultiPartFormDataStreamProviderWrapper : IMultiPartFormDataStreamProviderWrapper
    {
        public const string UploadPath = "~/Media/Default/Vocabulary/";
        private MultipartFormDataStreamProvider provider;

        public MultiPartFormDataStreamProviderWrapper(IHttpContextAccessor httpContextAccessor)
        {
            provider = new CustomMultipartFormDataStreamProvider(httpContextAccessor.Current().Server.MapPath(UploadPath));
        }

        public string LocalFileName
        {
            get { return provider.FileData[0].LocalFileName; }
        }


        public MultipartFormDataStreamProvider Provider
        {
            get { return provider; }
        }
    }

Итак, я мог бы сделать что-то вроде

    if (Request.Content.IsMimeMultipartContent())
    {
        return Request.Content.ReadAsMultipartAsync(provider.Provider).ContinueWith(t => 
                    {
                        if (t.IsCanceled || t.IsFaulted)
                            return (object)new { success = false };

Не идеален, но дает некоторое умение. Как вы думаете?

Ответ 4

Если вы еще не загрузили полотенце в веб-API, вы можете попробовать System.Net.Http.TestableMultipartStreamProviders, которые являются выпадающую переписку с поставщиками потоков Microsoft. Их преимуществом является то, что они полагаются на SystemWrapper для операций с файлами, что означает, что операции с файлами можно издеваться над модульными тестами. wiki дает некоторые идеи об использовании DI, чтобы сделать контрольные контролеры менее болезненными.