I have some test code that's preparing a MemoryStream
that will eventually be read by an object. Here's how I want to write it:
var manager = new LeaderboardImportManager(leaderboard);
var columnNames = manager.ColumnNames;
var stream = new MemoryStream();
using (var writer = new StreamWriter(stream))
{
writer.WriteLine(string.Join(",", columnNames));
foreach (var user in users)
{
var row = leaderboard.Metrics.Select(m => Faker.RandomNumber.Next().ToString()).ToList();
row.Insert(0, user.UserName);
writer.WriteLine(string.Join(",", row));
}
writer.Flush();
stream.Position = 0;
}
return stream;
But when I do it that way, my stream object becomes unreadable and my test fails, so I have to do it like this:
var manager = new LeaderboardImportManager(leaderboard);
var columnNames = manager.ColumnNames;
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.WriteLine(string.Join(",", columnNames));
foreach (var user in users)
{
var row = leaderboard.Metrics.Select(m => Faker.RandomNumber.Next().ToString()).ToList();
row.Insert(0, user.UserName);
writer.WriteLine(string.Join(",", row));
}
writer.Flush();
stream.Position = 0;
return stream;
This, of course, prevents me from being able to dispose of my StreamWriter
object, which as I understand it, should definitely be disposed of.
Why does the StreamWriter
need to remain open if I've flushed its contents to the MemoryStream
object already?
I can think of some very inconvenient ways to work around this, but I'd like to know why it doesn't work the way I want it, and whether or not there's something I can do to make it work that way. Any advice is appreciated, thanks!
The other answers indicate I should use the constructor that has a leaveOpen
param and set it to true, but I dislike this because the constructor also requires a bufferSize
argument.
However, I realized that I can get away with this just as easily:
// new method body, returns byte array
var stream = new MemoryStream();
using (var writer = new StreamWriter(stream))
{
writer.WriteLine(string.Join(",", columnNames));
foreach (var user in users)
{
var row = leaderboard.Metrics.Select(m => Faker.RandomNumber.Next().ToString()).ToList();
row.Insert(0, user.UserName);
writer.WriteLine(string.Join(",", row));
}
writer.Flush();
stream.Position = 0;
}
return stream.ToArray();
// consumer opens a new stream using the bytes
using (var stream = new MemoryStream(this.GetCSVStream(leaderboard, users)))
{
mockFile.Setup(f => f.InputStream).Returns(stream);
this.service.UpdateEntries(update.ID, mockFile.Object);
}