问题
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!
回答1:
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());
}
回答2:
Two essential things:
Console.ReadLine
is an external dependency and should be provided to your method in some way (preferably via dependency injection)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));
}
回答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
回答4:
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.
回答5:
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?
来源:https://stackoverflow.com/questions/10181421/how-do-i-apply-unit-testing-to-c-sharp-function-which-requires-user-input-dynami