Остановить mocked IFormFile от создания FileCopy

При написании модульных тестов для одного из моих классов обслуживания в веб-API ASP.Net Core мне нужно было имитировать IFormFile. Поэтому я решил поиздеваться над этим (используя moq):

fileMock.Setup(x => x.CopyToAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.Callback(() =>
{
    Console.WriteLine("File Copied");
})
.Returns(Task.CompletedTask);

Метод, который я хочу протестировать, с радостью принимает этот макет, и все выглядело нормально, пока я не проверил расположение файла, которое я указал для целей тестирования здесь:
Остановить mocked IFormFile от создания FileCopy.

Мне это показалось немного странным, поскольку я ожидал, что файл не будет создан (особенно потому, что мои операторы обратного вызова и возврата никогда не касаются потока). Я попытался изменить макет (например, без какого-либо обратного вызова или с немедленным закрытием потока), но не повезло, что файл все еще создается. Затем я проверил свою реализацию операции сохранения файла:

public async Task<Result> SaveFileToDiskAsync(string filePath, IFormFile file, CancellationToken token)
{
    //Checking if values are correct
    try
    {
        using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await file.CopyToAsync(stream, token).ConfigureAwait(false);
            return Result.Ok();
        }               
    }
    catch (Exception e)
    {
     //Logging
    }
}

И вот здесь я застрял. Я не вижу, что не так с этим методом, особенно потому, что он, кажется, правильно работает с копированием файла (он просто делает это не в то время). Поэтому мой вопрос: есть ли лучший способ реализовать макет или метод остановки создания файла?

var stream = new FileStream(filePath, FileMode.Create)буду создать файл. Вы тесно связаны с реальной проблемой реализации ввода-вывода. не абстракция, над которой можно посмеяться.
Nkosi 30.10.2018 01:30

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

Nkosi 30.10.2018 01:41
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
401
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
var stream = new FileStream(filePath, FileMode.Create) 

буду создать файл.

Система тесно связана с фактической реализацией ввода-вывода. Это не абстракция, над которой можно посмеяться.

Абстрагируйте доступ к файловому потоку.

public interface IFileStreamProvider {
    Stream Create(string path);
    Stream Open(string path);
    //...
}

Это должно дать системе необходимую гибкость, чтобы не беспокоиться о реализации.

private readonly IFileStreamProvider disk; //populated via constructor injection.

public async Task<Result> SaveFileToDiskAsync(string filePath, IFormFile file, CancellationToken token) {
    //Checking if values are correct
    try {
        using (var stream = disk.Create(filePath)) {
            await file.CopyToAsync(stream, token).ConfigureAwait(false);
            return Result.Ok();
        }               
    } catch (Exception e) {
        //Logging
    }
}

И протестировано изолированно

//...

var disk = new MemoryStream(); //
var diskMock = new Mock<IFileStreamProvider>();
diskMock
    .Setup(_ => _.Create(It.IsAny<string>()))
    .Returns(disk);

//...

Хотя фактическая реализация IFileStreamProvider.Create завершит создание FileStream.

Большое спасибо за этот замечательный пример и объяснение. Это многое прояснило.

Brezelmann 30.10.2018 02:15

Другие вопросы по теме