public static class Utils
{
/// <summary>
/// Creates a Writer object that writes either to a file or to a console stream.
/// </summary>
/// <param name="outFname">file name, "stdout" or "stderr"</param>
/// <param name="ifAppend">if true, append to existing file; otherwise, overwrite</param>
/// <returns>A TextWriter object that can be used to write output.</returns>
public static StreamWriter OutWriter(string outFname, bool ifAppend)
{
if (string.IsNullOrEmpty(outFname) || outFname == "stdout")
{
return new StreamWriter(Console.OpenStandardOutput());
}
else if (outFname == "stderr")
{
return new StreamWriter(Console.OpenStandardError());
}
else
{
FileStream fileStream;
if (ifAppend)
fileStream = new FileStream(outFname, FileMode.Append, FileAccess.Write, FileShare.None);
else
fileStream = new FileStream(outFname, FileMode.Create, FileAccess.Write, FileShare.None);
return new StreamWriter(fileStream, Encoding.UTF8);
}
}
}
[TestMethod]
public void OutWriter_ShouldReturnConsoleError_ForStderr()
{
// Capture the current Console.Error
TextWriter originalError = Console.Error;
// Redirect Console.Error to a StringWriter to capture the output
StringWriter errorWriter = new StringWriter();
Console.SetError(errorWriter);
using (StreamWriter writer = Utils.OutWriter("stderr", false))
{
// Write something to the StreamWriter
writer.WriteLine("Test error output");
writer.Flush(); // Ensure the output is flushed
}
// Reset the Console.Error to its original state
Console.SetError(originalError);
// Verify that the output was written to the StringWriter
string expectedOutput = "Test error output" + Environment.NewLine;
string actualOutput = errorWriter.ToString();
Assert.AreEqual(expectedOutput, actualOutput, "The writer should write to Console.Error.");
}
Test output:
Test Name: OutWriter_ShouldReturnConsoleError_ForStderr
Test FullName: PdbLibTests.UtilsTests.OutWriter_ShouldReturnConsoleError_ForStderr
Test Source: C:\git\MyProject_csharp\unit_test_for_Utils\UtilsTests.cs : line 15
Test Outcome: Failed
Test Duration: 0:00:00.1644456
Result StackTrace: at PdbLibTests.UtilsTests.OutWriter_ShouldReturnConsoleError_ForStderr() in C:\git\MyProject_csharp\unit_test_for_Utils\UtilsTests.cs:line 37
Result Message:
Assert.AreEqual failed. Expected:<Test error output
>. Actual:<>. The writer should write to Console.Error.
Why isn't the unit-test succeeding?
How can I make it succeed?
Then I tried mocking the console:
public static class MockConsole
{
public static StringWriter ErrorWriter { get; private set; }
public static TextWriter OriginalError { get; private set; }
public static void Initialize()
{
OriginalError = Console.Error;
ErrorWriter = new StringWriter();
Console.SetError(ErrorWriter);
}
public static void Reset()
{
Console.SetError(OriginalError);
ErrorWriter.Dispose();
}
}
[TestMethod]
public void OutWriter_ShouldReturnConsoleError_ForStderr()
{
// Initialize mock console
MockConsole.Initialize();
using (StreamWriter writer = Utils.OutWriter("stderr", false))
{
// Write something to the StreamWriter
writer.WriteLine("Test error output");
writer.Flush(); // Ensure the output is flushed
}
// Capture the output written to the error writer
string actualOutput = MockConsole.ErrorWriter.ToString();
// Reset the console to its original state
MockConsole.Reset();
// Verify that the output was written to the StringWriter
string expectedOutput = "Test error output" + Environment.NewLine;
Assert.AreEqual(expectedOutput, actualOutput, "The writer should write to Console.Error.");
}
This also hasn't succeeded.
OutWriter
to begin with? The correct way to test this would be to use a stream as input. Once you do that though,OutWriter
isn't very useful. If you want to log to the console or a file, it's a lot better (and faster, easier) to use a logging library like Serilogreturn new StreamWriter(stream);
. Using switch expressions you could turn all this in 3-4 lines that pick a stream. I'd still use Serilog instead