13

The function below gets input from the user. I need to test this function using Unit Testing. Can anyone tell me how to test this kind of function which require user input dynamically. Thanks

like boundary value analysis ...

numberOfCommands should be (0 <= n <= 100)

public static int Get_Commands()
{
    do
    {
        string noOfCommands = Console.ReadLine().Trim();
        numberOfCommands = int.Parse(noOfCommands);             
    }
    while (numberOfCommands <= 0 || numberOfCommands >= 100);  

    return numberOfCommands;
}

Programmatically hint will be great help!

k.m
  • 30,794
  • 10
  • 62
  • 86
rana
  • 145
  • 1
  • 2
  • 8
  • Just run the program. Give input. do you mean by unit testing? – Sandeep Apr 16 '12 at 20:48
  • yes for unit testing .. like boundary value testing for `numberOfCommands` should be `0 <= n <= 100`. – rana Apr 16 '12 at 21:36
  • Does this answer your question? [C# unit test for a method which calls Console.ReadLine()](https://stackoverflow.com/questions/3161341/c-sharp-unit-test-for-a-method-which-calls-console-readline) – Artur INTECH Feb 15 '23 at 08:47

5 Answers5

14

Create an interface and pass in the interface to receive text. Then, in your unit test, pass in a mock interface that automatically returns some result.

Edit for code details:

public interface IUserInput{
    string GetInput();
}

public static int Get_Commands(IUserInput input){
    do{
       string noOfCommands = input.GetInput();
       // Rest of code here
    }
 }

public class Something : IUserInput{
     public string GetInput(){
           return Console.ReadLine().Trim();
     }
 }

 // Unit Test
 private class FakeUserInput : IUserInput{
      public string GetInput(){
           return "ABC_123";
      }
 }
 public void TestThisCode(){
    GetCommands(new FakeUserInput());
 }
Josh
  • 10,352
  • 12
  • 58
  • 109
4

Two essential things:

  1. Console.ReadLine is an external dependency and should be provided to your method in some way (preferably via dependency injection)
  2. Console.ReadLine uses TextReader base class under the hood, and that's what should be provided

So, what your method needs is dependency to TextReader (you could abstract it even more with your custom interface, but for purpose of testing it is enough):

 public static int Get_Commands(TextReader reader)
 {
     // ... use reader instead of Console
 }

Now, in real application you invoke Get_Commands using real console:

    int commandsNumber = Get_Commands(Console.In);

In your unit test, you create fake input using for example StringReader class:

[Test]
public void Get_Commands_ReturnsCorrectNumberOfCommands()
{
   const string InputString = 
       "150" + Environment.NewLine + 
       "10" + Environment.NewLine;
   var stringReader = new StringReader(InputString);

   var actualCommandsNumber = MyClass.Get_Commands(stringReader);

   Assert.That(actualCommandsNumber, Is.EqualTo(10));
}
k.m
  • 30,794
  • 10
  • 62
  • 86
3

You can use Console.SetIn() and Console.SetOut() to define the input and output. Use StringReader to define the test's input, and StringWriter to capture the output.

You can see my blog post on the subject, for a more complete explanation and example: http://www.softwareandi.com/2012/02/how-to-write-automated-tests-for.html

Assaf Stone
  • 6,309
  • 1
  • 34
  • 43
1

You can redirect input from a file to standard input, and use that in your tests. You can do that programmatically in the program itself, or through the shell that runs the program.

You could also extrapolate everything 'user input' into their own classes/functions so that it's easy to replace a function that 'gets a line of text from the user' with a function that 'returns this hard coded string for testing'. If each of these functions are in classes that implement a common interface it makes switching them out very easy.

Servy
  • 202,030
  • 26
  • 332
  • 449
-1

In Main() you can just do:

int testCommand=Get_Commands();
Console.WriteLine(testCommand);

However, I don't know if that's the type of test you were wanting. Is there more to the question than simply testing the result of the function?

Kaizen Programmer
  • 3,798
  • 1
  • 14
  • 30