Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking 'System.Console' behaviour

Is there a standard way of making a C# console application unit-testable by programming against an interface, rather than System.Console?

For example, using an IConsole interface?

Have you done this, and what kind of methods did you use?

Did you expose events for when your application needs to write to the standard output?

like image 481
Jonathan Avatar asked May 02 '11 01:05

Jonathan


People also ask

What does system console do?

The console is an operating system window where users interact with the operating system or with a text-based console application by entering text input through the computer keyboard, and by reading text output from the computer terminal.

What is console method in C#?

A console application, in the context of C#, is an application that takes input and displays output at a command line console with access to three basic data streams: standard input, standard output and standard error.


2 Answers

I think your approach with an interface would work, and I don't think I would make use of events. Assuming the application does not accept user input other than command line parameters, I would probably use something like this to wrap Console.Write/Console.WriteLine:

public interface IConsoleWriter
{
    void Write(string format, params object[] args);
    void WriteLine(string format, params object[] args);
}

To test, I would either create a TestConsoleWriter that would store all writes into a buffer that I could then assert against, or I would create a mock and verify that Write or WriteLine was called with the parameters I expected. If your application is going to be doing a ton of writing to the console (say +100 MB or so of output), then using a mock would probably be preferable for performance reasons, but otherwise I would say pick whichever method you think would be easier to work with.

This approach does have a few limitations, however. If you are using any assemblies that you cannot modify and they write to the console, then you won't see that output since you can't force those classes to use your IConsoleWriter. Another problem is that the Write and WriteLine methods have 18 or so overloads, so you may be wrapping alot of methods. To get around these limitations, you may just want to use the Console.SetOut method to redirect the console output to your own TextWriter while testing.

Personally, I think I would take the SetOut approach. It would just be one line you have to add at the beginning of your unit tests (or possibly in a SetUp method) and you can just assert against what is written into the TextWriter.

like image 60
rsbarro Avatar answered Nov 23 '22 07:11

rsbarro


You want to change the stream that console writes to in your unit tests. Then you can put in a mock stream or whatever. Check this post by Mark Seemann on testing Console:

http://blogs.msdn.com/b/ploeh/archive/2006/10/21/consoleunittesting.aspx

like image 22
xofz Avatar answered Nov 23 '22 07:11

xofz