Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test "console.readLine" for invalid input?

I am scratching my head on this little problem.

I have this line and 3 other similar ones in a method

try
{
    int PhoneIMEINumber = int.Parse(Console.ReadLine());
}

{
catch(Exception)
{
    return null;
}

If the user enters "abcd" for input, this throws an exception and I can catch it and show an error message.

But how do I make a unit test for this? I can't simulate console input from the unit test ofcourse and I want to check from my unit test if a null was returned.

Thank you

like image 584
iAteABug_And_iLiked_it Avatar asked Jul 26 '13 18:07

iAteABug_And_iLiked_it


People also ask

How does the ReadLine () method work?

The C# readline method is mainly used to read the complete string until the user presses the Enter key or a newline character is found. Using this method, each line from the standard data input stream can be read. It is also used to pause the console so that the user can take a look at the output.

What is the purpose of console ReadLine () method?

One of the most common uses of the ReadLine method is to pause program execution before clearing the console and displaying new information to it, or to prompt the user to press the Enter key before terminating the application.

What is the difference between console Writeline () and console ReadLine ()?

The only difference between the Read() and ReadLine() is that Console. Read is used to read only single character from the standard output device, while Console. ReadLine is used to read a line or string from the standard output device. Program 1: Example of Console.

Is console ReadLine a string?

The Console. ReadLine() method reads and only returns the string from the stream output device (console) until a newline character is found. If we want to read a character or numeric value from the user, we need to convert the string to the appropriate data sets.


2 Answers

If you want to Unit Test the Console then you'll probably need to create a wrapper interface.

public interface IConsole
{
    string ReadLine();
}

public class ConsoleWrapper : IConsole
{
    public string ReadLine()
    {
        return Console.ReadLine();
    }
}

This way you can create a Stub/Fake to test your business rules.

public class TestableConsole : IConsole
{
    private readonly string _output;

    public TestableConsole(string output)
    {
        _output = output;
    }

    public string ReadLine()
    {
        return _output;
    }
}

Inside the test:

public class TestClass
{
    private readonly IConsole _console;

    public TestClass(IConsole console)
    {
        _console = console;
    }

    public void RunBusinessRules()
    {
        int value;
        if(!int.TryParse(_console.ReadLine(), out value)
        {
            throw new ArgumentException("User input was not valid");
        }
    }
}

[Test]
public void TestGettingInput()
{
    var console = new TestableConsole("abc");

    var classObject = new TestClass(console);

    Assert.Throws<ArgumentException>(() => classObject.RunBusinessRules());
}

I would go with trying to avoid Unit Testing the Console and taking a dependency on it.

like image 184
Dustin Kingen Avatar answered Sep 21 '22 11:09

Dustin Kingen


You can set Console.In to a given text reader using SetIn:

var sr = new StringReader("Invalid int");
Console.SetIn(sr);

int? parsed = MethodUnderTest();
Assert.IsNull(parsed);
like image 41
Lee Avatar answered Sep 25 '22 11:09

Lee