Остановите надуманный IFormFile от создания FileCopy - PullRequest
0 голосов
/ 30 октября 2018

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

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

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

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

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
    }
}

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

1 Ответ

0 голосов
/ 30 октября 2018
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.

...