views:

54

answers:

2

If I have a function which accepts an out parameter and accepts an input form console -

public void Test(out int a)
{
     a = Convert.ToInt16(Console.ReadLine());  
}

How can I accept an input using Console.Readline() during NUnit test? How can I use NUnit to test this method?

I tried using this code for my NUnit test case -

[TestCase]
public void test()
{
     int a = 0;   
     ClassAdd ad = new ClassAdd();
     ad.addition(out a);

     //a should be equal to the value I input through console.Readline()
     Assert.AreEqual(<some value I input>, a, "test");    
}

how can I test a method which accepts an out parameter and also accepts an user input from Console?

+2  A: 

You can use the SetIn method of System.Console to set the the input source:

StringReader reader = new StringReader("some value I input" + Enivronment.NewLine);
Console.SetIn(reader);

int a = 0;   
ClassAdd ad = new ClassAdd();
ad.addition(out a);

Assert.AreEqual(<some value I input>, a, "test");

EDIT: To test multiple values, just separate each input with a new line:

string[] lines = new[] { "line1", "line2" };
StringReader input = new StringReader(String.Join(Environment.NewLine, lines));
Console.SetIn(input);

string input1 = Console.ReadLine();    //will return 'line1'
string input2 = Console.ReadLine();    //will return 'line2'
Lee
Oh Thanks. If I have multiple input values i.e. I have to accept more than one value from the Console. How can I do that?
Pavanred
+1 That's nice to know. Instead of mocking out `Console`, you can mock out its reader. This would certainly help where a class depends on `Console`, but hasn't been designed for testability.
Craig Young
+1  A: 

There are 2 slightly different issues combined here.

  1. You want to test a method that returns a value in an out parameter. This is actually quite trivial and is hardly different from a method that returns its value as a normal function.
  2. You want to test a method that reads input form the console. This one is quite a bit trickier, and goes a little into the design of the object you're trying to test. The problem is that the "Console" is a global object, and that immediately makes it more difficult to test.

The craziest thing to note is that you want to test a method that takes input from the console. I.e. this implies user interaction. This is hardly the way to go about "automated testing" don't you think?

In answer to #2, I suggest you look at some of Misko Hevery's articles and videos on writing testable code.

http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/

For a brief summary specfic to your problem:

  • MethodToTest currently wants input from the console.
  • The class that holds MethodToTest should take an "input stream" in its constructor. (This is a technique called dependency injection.)
  • In production code, your class will be created with the normal "Console" as its input stream.
  • In test code, the class will be constructed with a Mock input stream that will feed values controlled by the test.
  • In this way your test can be automated, and well controlled in terms of inputs; and therefore expected outputs.

Bare Bones Sample Code

[TestCase] 
public void test() 
{ 
  <use appropriate type here> MockInputStream = new ...;
  ClassToTest testClass = new ClassToTest(MockInputStream);

  int Actual = 0;
  MockInputStream.PutNextInput("4");
  ClassToTest.MethodToTest(out Actual);

  Assert.AreEqual(4, Actual, "MockInputStream placed 4 as the next value to read");
} 
Craig Young