我在这个小问题上摸不着头脑。
我在一个方法中有这条线和其他 3 条类似的线
try
{
int PhoneIMEINumber = int.Parse(Console.ReadLine());
}
{
catch(Exception)
{
return null;
}
如果用户输入“abcd”进行输入,则会引发异常,我可以捕获它并显示错误消息。
但是我该如何为此进行单元测试呢?我当然无法从单元测试中模拟控制台输入,我想从单元测试中检查是否返回了空值。
谢谢
我在这个小问题上摸不着头脑。
我在一个方法中有这条线和其他 3 条类似的线
try
{
int PhoneIMEINumber = int.Parse(Console.ReadLine());
}
{
catch(Exception)
{
return null;
}
如果用户输入“abcd”进行输入,则会引发异常,我可以捕获它并显示错误消息。
但是我该如何为此进行单元测试呢?我当然无法从单元测试中模拟控制台输入,我想从单元测试中检查是否返回了空值。
谢谢
如果您想进行单元测试,Console
那么您可能需要创建一个包装器接口。
public interface IConsole
{
string ReadLine();
}
public class ConsoleWrapper : IConsole
{
public string ReadLine()
{
return Console.ReadLine();
}
}
这样您就可以创建一个 Stub/Fake 来测试您的业务规则。
public class TestableConsole : IConsole
{
private readonly string _output;
public TestableConsole(string output)
{
_output = output;
}
public string ReadLine()
{
return _output;
}
}
测试内部:
public class TestClass
{
private readonly IConsole _console;
public TestClass(IConsole console)
{
_console = console;
}
public void RunBusinessRules()
{
int value;
if(!int.TryParse(_console.ReadLine(), out value)
{
throw new ArgumentException("User input was not valid");
}
}
}
[Test]
public void TestGettingInput()
{
var console = new TestableConsole("abc");
var classObject = new TestClass(console);
Assert.Throws<ArgumentException>(() => classObject.RunBusinessRules());
}
我会尽量避免单元测试Console
并依赖它。
您可以使用SetInConsole.In
设置为给定的文本阅读器:
var sr = new StringReader("Invalid int");
Console.SetIn(sr);
int? parsed = MethodUnderTest();
Assert.IsNull(parsed);
就像发布的两条评论一样。我会考虑重构你的代码看起来更像
string input = Console.ReadLine();
try
{
int PhoneIMEINumber = parse_input(input);
}
catch(Exception)
{
return null;
}
然后你会有一个功能
public int parse_input(string input)
{
return int.Parse(input);
}
然后你会为这个parse_input
函数编写一个单元测试。尽管示例代码看起来很简单,而且很难证明围绕 int.Parse() 的包装函数编写单元测试是合理的,但我假设您的解析将来可能会变得更加复杂。
要对代码进行单元测试,那段代码需要是可测试的。
为了对一个方法进行单元测试,我们要做的是传入一些已知的输入并检查它是否返回了预期的结果,或者我们是否有正确的副作用。
现在,如果你直接在你的方法中输入你的输入,它就不是很可测试的。它有两个部分,读取输入和处理它。如果您的测试中的断言失败,您不知道哪一步失败了。单元测试应该旨在测试代码的单元或单一职责。
为了使其可测试,在 main 方法中读取输入并将其传递给另一个方法进行处理(也是面向对象编程的常见概念),并使用已知参数测试第二种方法。