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

I scratch my head with this little problem.

I have this line and 3 other similar methods in

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 do a unit test for this? I cannot simulate console input from unit test, and I want to check from my unit test if null was returned.

thanks

+4
source share
4 answers

Like the two posted comments. I would think that refactoring your code would look like something more like

 string input = Console.ReadLine(); try { int PhoneIMEINumber = parse_input(input); } catch(Exception) { return null; } 

and then you will have a function

 public int parse_input(string input) { return int.Parse(input); } 

Then you write unit test for the parse_input function. The sample code seems rather trivial, although it is difficult to justify the unit test notation around the wrapper function for int.Parse (), but I assume that your analysis may become more complicated in the future.

+5
source

If you want Unit Test Console , you probably need to create a shell interface.

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

This way you can create 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 try to avoid the Unit Testing Console and depend on it.

+7
source

You can install Console.In in a given text reader using SetIn :

 var sr = new StringReader("Invalid int"); Console.SetIn(sr); int? parsed = MethodUnderTest(); Assert.IsNull(parsed); 
+6
source

In unit test code, this piece of code should be checked.

In the unit test method, what we do goes through some known input and checks if it returns the expected result or if we have the right side effect.

Now, if you directly take your input inside your method, it is not very validated. It has two parts, reading the input data and processing them. If the assertion in your test fails, you don’t know which step failed. unit test should be aimed at unit testing or single code responsibility.

To make it suitable for testing, read the input in the main method and pass it to another processing method (also the general concept of object-oriented programming) and test the second method with known parameters.

0
source

Source: https://habr.com/ru/post/1493739/


All Articles