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.
Comments
-
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 about 9 yearsMy function expect data from excel file. test_Stream = File.Open("C:/Excel file.xls", FileMode.Open, FileAccess.Read);
-
GazTheDestroyer about 9 yearsAny reason you can't just load a test file like that?
-
Raskolnikov about 9 yearsI don't have permission to write integration test:)
-
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 about 9 yearsHow to mock stream with any meaningful data ?
-
David Arno about 9 yearsThat won't help as apparently the method requires Excel data in the stream (see comments to GazTheDestroyer's answer).
-
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 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 about 9 yearsHave added info on how to add the file as a resource
-
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 over 8 yearsBy the way, reading from a file turns the test into something different from what is broadly understood as an Unit Test.
-
Jonathan Gilbert over 7 yearsI 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-inMemoryStream
type can supply an interface betweenStream
semantics andbyte[]
buffers. So, this answer does not accurately characterize the problem space or potential solutions. -
Jonathan Gilbert over 7 yearsI 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 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 over 7 yearsUltimately, 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 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 over 7 yearsOkay, yes, it is technically true that you can use a mocking framework to make a mock
Stream
object. But, you can create a mockStream
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 over 6 yearsThis is incorrect, the Microsoft Fakes are not paid.The answer should be deleted.
-
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