您的代码基本上无法测试。
该方法做的工作太多。它应该分成几个较小的,可以单独测试。
你应该摆脱静态方法。因为你不能把它们弄假。
应该通过网络(我看到使用 WebSocket)以及从数据库或文件系统获取数据。您应该将现成的数据传递给此方法。
这里是修改后的代码,分解成小方法。日志和事件已从代码中删除,以免解释复杂化。
public class App
{
private readonly Random _random = new Random();
private Task<int> GetRandomNumber(int min, int max)
{
return Task.FromResult(_random.Next(min, max));
}
internal int GetInput()
{
Console.WriteLine("Please guess a number between 1 and 100");
int value;
while (true)
{
string input = Console.ReadLine();
bool result = int.TryParse(input, out value);
if (!result)
Console.WriteLine("Not a number");
else if (value < 1 || value > 100)
Console.WriteLine("Must be between 1 and 100");
else
break;
}
return value;
}
internal bool PlayAgain()
{
Console.WriteLine("Do you want to play again?");
string input = Console.ReadLine();
return input == "Y" || input == "y";
}
internal void Guessing(int randomNumber)
{
int attempts = 1;
while (attempts < 10)
{
var inputNumber = GetInput();
// logging
if (inputNumber == randomNumber)
{
// OnSuccesfulGuess
return;
}
else
{
// OnWrongGuessWithinAttempts
}
attempts++;
}
Console.WriteLine("Oops, maybe next time.");
// logging
}
public async Task RunAsync()
{
do
{
int randomNumber = await GetRandomNumber(1, 100);
Guessing(randomNumber);
}
while (PlayAgain());
}
}
现在我们可以测试单个方法了。
我使用 MSTest。
[DataTestMethod]
[DataRow("Y")]
[DataRow("y")]
public void PlayAgain_InputY_ReturnsTrue(string value)
{
using (var reader = new StringReader(value))
{
Console.SetIn(reader);
var app = new App();
bool result = app.PlayAgain();
Assert.IsTrue(result);
}
}
[DataTestMethod]
[DataRow("N")]
[DataRow("boo")]
[DataRow("")]
public void PlayAgain_InputNotY_ReturnsFalse(string value)
{
using (var reader = new StringReader(value))
{
Console.SetIn(reader);
var app = new App();
bool result = app.PlayAgain();
Assert.IsFalse(result);
}
}
我们对其他方法做同样的事情。
这是GetInput 方法的测试。
由于输入错误值时内部存在无限循环,因此我们必须通过输入正确值来中断它。这是通过通过换行传递两个值来完成的:"0\n50"。输入不正确的值是对输出字符串的测试,然后用正确的值中断循环。
[DataTestMethod]
[DataRow("1")]
[DataRow("50")]
[DataRow("100")]
public void GetInput_InputCorrectString_ReturnsNumber(string value)
{
using (var reader = new StringReader(value))
{
Console.SetIn(reader);
var app = new App();
int actual = app.GetInput();
int expected = int.Parse(value);
Assert.AreEqual(expected, actual);
}
}
[DataTestMethod]
[DataRow("0\n50")]
[DataRow("101\n50")]
public void GetInput_InputSmallerOrGreaterValue_WritesMessage(string value)
{
using (var reader = new StringReader(value))
using (var writer = new StringWriter())
{
Console.SetIn(reader);
Console.SetOut(writer);
var app = new App();
_ = app.GetInput();
string actualMessage = writer.ToString();
string expectedMessage = "Must be between 1 and 100";
Assert.IsTrue(actualMessage.Contains(expectedMessage));
}
}
[DataTestMethod]
[DataRow("x\n50")]
[DataRow("qwerty\n50")]
public void GetInput_InputNotNumber_WritesMessage(string value)
{
using (var reader = new StringReader(value))
using (var writer = new StringWriter())
{
Console.SetIn(reader);
Console.SetOut(writer);
var app = new App();
_ = app.GetInput();
string actualMessage = writer.ToString();
string expectedMessage = "Not a number";
Assert.IsTrue(actualMessage.Contains(expectedMessage));
}
}