How to write unitTest for methods using a stream as a parameter

38,202

Solution 1

Use a MemoryStream. Not sure what your function expects, but to stuff a UTF-8 string into it for example:

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

    // Assert    
    Assert.IsTrue(result);
}

EDIT: If you need an Excel file, and you are unable to read files from disk, could you add an Excel file as an embedded resource in your test project? See How to embed and access resources by using Visual C#

You can then read as a stream like this:

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

    // Assert    
    Assert.IsTrue(result);
}

Solution 2

You can use a MemoryStream to provide a purely in-memory stream for your test.

Share:
38,202
Raskolnikov
Author by

Raskolnikov

hi

Updated on July 22, 2022

Comments

  • Raskolnikov
    Raskolnikov almost 2 years

    I have class ImportProvider , and I want write unit test for Import method.

    But this should be unit test, so I don't want to read from file to stream. Any idea?

    public class ImportProvider : IImportProvider
    { 
         public bool Import(Stream stream)
         {
             //Do import
    
             return isImported;
         }
    }
    
    public interface IImportProvider
    {
          bool Import(Stream input);
    }
    

    This is 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);
    }
    
  • Raskolnikov
    Raskolnikov about 9 years
    My function expect data from excel file. test_Stream = File.Open("C:/Excel file.xls", FileMode.Open, FileAccess.Read);
  • GazTheDestroyer
    GazTheDestroyer about 9 years
    Any reason you can't just load a test file like that?
  • Raskolnikov
    Raskolnikov about 9 years
    I don't have permission to write integration test:)
  • David Arno
    David Arno about 9 years
    @user2451446, so your real problem is that you want to feed the contents of an Excel file into the code under test but do not want to read that data from an excel file. You're going to have to compromise somewhere: either make it an integration test or remove the dependency on the specific content of the stream.
  • Raskolnikov
    Raskolnikov about 9 years
    How to mock stream with any meaningful data ?
  • David Arno
    David Arno about 9 years
    That won't help as apparently the method requires Excel data in the stream (see comments to GazTheDestroyer's answer).
  • MistyK
    MistyK about 9 years
    @user2451446 it depends what is the content of Import method, what is used, what is expected etc DavidArno I don't understand what do you mean? If you wrap whole stream class you will be able to use all functionality that stream provides but with another class, I don't understand where would it fail.
  • David Arno
    David Arno about 9 years
    @Zbigniew, that mock class would have to supply Excel data when requested. That data can't be read from a file ... so the OP has an impossible situation. The mock class doesn't solve anything that a MemoryStream can't solve too.
  • GazTheDestroyer
    GazTheDestroyer about 9 years
    Have added info on how to add the file as a resource
  • David Arno
    David Arno about 9 years
    @GazTheDestroyer, I love it when I claim a dichotomy of poor choices and someone adds a third, perfect solution, choice to the mix. I never thought of resources. That completely solves the OP's needs. Sadly I can't +1 a second time :)
  • Ignacio Soler Garcia
    Ignacio Soler Garcia over 8 years
    By the way, reading from a file turns the test into something different from what is broadly understood as an Unit Test.
  • Jonathan Gilbert
    Jonathan Gilbert over 7 years
    I think it comes down to two things: 1) There are mocking frameworks like NSubstitute that are completely free to use, and 2) streams can be "mocked" without having to mock the actual stream type, because a) the Stream type itself can be directly extended in arbitrary subclasses, and b) if all you need is to be able to read or write data, the built-in MemoryStream type can supply an interface between Stream semantics and byte[] buffers. So, this answer does not accurately characterize the problem space or potential solutions.
  • Jonathan Gilbert
    Jonathan Gilbert over 7 years
    I disagree. If the file is embedded into the test, then it is still test vs. one unit of code. You abstract away where the data actually comes from and test just that the data can be processed correctly. There are multiple ways to embed the data. The most obvious are to either generate an actual file and then make it an "Embedded Resource", or to write code against an Excel DOM provider of some sort that dynamically generates data in the expected format.
  • Jonathan Gilbert
    Jonathan Gilbert over 7 years
    ...and if you use code to generate an Excel file automatically at runtime (and then e.g. save it to a MemoryStream), you have the choice of either always generating exactly the same data, or of generating the data randomly -- in the latter case, you use an unpredictable seed for a pseudo-random number generator and output the seed as part of the test output, so that if it fails, the result can be replicated in subsequent debug runs to diagnose the issue.
  • Jonathan Gilbert
    Jonathan Gilbert over 7 years
    Ultimately, as long as the data isn't coming from outside of the test, there is no real semantic difference between a string literal and an "Excel file literal" being used as input for a test case.
  • Ignacio Soler Garcia
    Ignacio Soler Garcia over 7 years
    @JonathanGilbert: you may think that there are other options and you may think that they are better than this one but I think that it is not arguable that an isolation framework IS a potential solution for this problem.
  • Jonathan Gilbert
    Jonathan Gilbert over 7 years
    Okay, yes, it is technically true that you can use a mocking framework to make a mock Stream object. But, you can create a mock Stream object more easily with a simple subclass. On top of it, you state in your answer that all mocking frameworks are paid, which is just plain untrue. So, your answer is misleading, even if the first half of it is technically true, and your answer suggests doing something "the hard way", without indicating or acknowledging that there is an easier way. That is why other Stack Overflow members have rated it a poor answer.
  • Skorunka František
    Skorunka František over 6 years
    This is incorrect, the Microsoft Fakes are not paid.The answer should be deleted.
  • Ignacio Soler Garcia
    Ignacio Soler Garcia over 6 years
    @SkorunkaFrantišek: not paid? It is only available on Visual Studio ultimate or premium. Do you know how much is each of these? It's the most expensive one :D