Pet*_*bev 11 c# console unit-testing visual-studio console-redirect
我想为一个类的成员函数创建一个单元测试,该类函数ScoreBoard存储游戏中的前五名玩家.
问题是我为(SignInScoreBoard)创建的测试方法是调用,Console.ReadLine()所以用户可以输入他们的名字:
public void SignInScoreBoard(int steps)
{
if (topScored.Count < 5)
{
Console.Write(ASK_FOR_NAME_MESSAGE);
string name = Console.ReadLine();
KeyValuePair<string, int> pair = new KeyValuePair<string, int>(name, steps);
topScored.Insert(topScored.Count, pair);
}
else
{
if (steps < topScored[4].Value)
{
topScored.RemoveAt(4);
Console.Write(ASK_FOR_NAME_MESSAGE);
string name = Console.ReadLine();
topScored.Insert(4, new KeyValuePair<string, int>(name, steps));
}
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法插入十个用户,所以我可以检查是否存储了五个较少的移动(步骤)?
Ree*_*sey 24
您需要将调用Console.ReadLine的代码行重构为一个单独的对象,因此您可以在测试中使用自己的实现将其存根.
作为一个简单的例子,你可以像这样创建一个类:
public class ConsoleNameRetriever {
public virtual string GetNextName()
{
return Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在您的方法中,重构它以取代此类的实例.但是,在测试时,您可以使用测试实现覆盖它:
public class TestNameRetriever : ConsoleNameRetriever {
// This should give you the idea...
private string[] names = new string[] { "Foo", "Foo2", ... };
private int index = 0;
public override string GetNextName()
{
return names[index++];
}
}
Run Code Online (Sandbox Code Playgroud)
测试时,使用测试实现交换实现.
当然,我个人会使用一个框架来使这更容易,并使用一个干净的界面而不是这些实现,但希望上面的内容足以给你正确的想法......
ang*_*son 14
您应该重构代码以从此代码中删除对控制台的依赖性.
例如,你可以这样做:
public interface IConsole
{
void Write(string message);
void WriteLine(string message);
string ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
然后像这样更改你的代码:
public void SignInScoreBoard(int steps, IConsole console)
{
... just replace all references to Console with console
}
Run Code Online (Sandbox Code Playgroud)
要在生产中运行它,请传递此类的实例:
public class ConsoleWrapper : IConsole
{
public void Write(string message)
{
Console.Write(message);
}
public void WriteLine(string message)
{
Console.WriteLine(message);
}
public string ReadLine()
{
return Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,在测试时,请使用:
public class ConsoleWrapper : IConsole
{
public List<String> LinesToRead = new List<String>();
public void Write(string message)
{
}
public void WriteLine(string message)
{
}
public string ReadLine()
{
string result = LinesToRead[0];
LinesToRead.RemoveAt(0);
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
这使您的代码更容易测试.
当然,如果要检查是否也写入了正确的输出,则需要向write方法添加代码以收集输出,以便您可以在测试代码中对其进行断言.
您不必模拟来自框架的某些内容,.NET 已经为其组件提供了抽象。对于控制台,它们是方法 Console.SetIn() 和 Console.SetOut()。
例如,对于 Console.Readline(),您可以这样做:
[TestMethod]
MyTestMethod()
{
Console.SetIn(new StringReader("fakeInput"));
var result = MyTestedMethod();
StringAssert.Equals("fakeInput", result);
}
Run Code Online (Sandbox Code Playgroud)
考虑到测试方法返回 Console.Readline() 读取的输入。该方法将使用我们设置为控制台输入的字符串,而不是等待交互式输入。
| 归档时间: |
|
| 查看次数: |
11720 次 |
| 最近记录: |