Как написать unitTest для методов, использующих поток в качестве параметра

У меня есть класс ImportProvider, и я хочу написать unit test для метода импорта.

Но это должно быть unit test, поэтому я не хочу читать из файла в поток. Любая идея?

public class ImportProvider : IImportProvider
{ 
     public bool Import(Stream stream)
     {
         //Do import

         return isImported;
     }
}

public interface IImportProvider
{
      bool Import(Stream input);
}

Это unit test:

[TestMethod]
public void ImportProvider_Test()
{
    // Arrange           
    var importRepository = new Mock<IImportRepository>(); 
    var imp = new ImportProvider(importRepository.Object);
    //Do setup...

    // Act
    var test_Stream = ?????????????
    // This working but not option:
    //test_Stream = File.Open("C:/ExcelFile.xls", FileMode.Open, FileAccess.Read);
    var result = imp.Import(test_Stream);

    // Assert    
    Assert.IsTrue(result);
}

Ответ 1

Используйте MemoryStream. Не уверен, что ожидает ваша функция, но вставляет в нее строку UTF-8, например:

//Act
using (var test_Stream = new MemoryStream(Encoding.UTF8.GetBytes("whatever")))
{
    var result = imp.Import(test_Stream);

    // Assert    
    Assert.IsTrue(result);
}

EDIT: если вам нужен файл Excel, и вы не можете читать файлы с диска, можете ли вы добавить файл Excel в качестве встроенного ресурса в тестовый проект? См. Как встраивать и получать доступ к ресурсам с помощью Visual С#

Затем вы можете читать как поток следующим образом:

//Act
using (var test_Stream = this.GetType().Assembly.GetManifestResourceStream("excelFileResource"))
{
    var result = imp.Import(test_Stream);

    // Assert    
    Assert.IsTrue(result);
}

Ответ 2

Вы можете использовать MemoryStream, чтобы обеспечить чисто поток в памяти для вашего теста.

Ответ 3

Используйте среду изоляции, такую ​​как JustMock, TypeMock или Microsoft Fakes, и вы сможете издеваться над потоком.

Плохая новость в том, что все они, насколько мне известно, оплачиваются.

Ответ 4

Мое решение состоит в том, чтобы обернуть Stream в свой собственный класс, назовите его StreamWrapper, который реализует интерфейс IStream. Теперь измените подпись импорта на

public bool Import(IStream stream)

Теперь вы можете издеваться над этим потоком, и если вы хотите использовать его в производственном коде, вы должны передать StreamWrapper в противном случае Mock.