测试我是否可以遍历字典并将键和值写入控制台
Test that I can iterate through dictionary and write keys and values to console
我正在尝试使用 TDD 在 C# 中编写一个控制台应用程序(我对此非常陌生)。
我正在尝试遍历包含字符串作为键和整数作为值的字典,并将它们作为 "key: value" 输出到控制台。我尝试了很多不同的东西,终于找到了一些可能有用的东西:
public void ShowContents ()
{
foreach (KeyValuePair<string, int> item in dictionary) {
Console.WriteLine ("{0}: {1}", item.Key, item.Value);
}
}
我遇到的问题是 - 我不知道如何测试它。我的测试目前看起来像这样:
[Test ()]
public void CanShowContentsOfDictionary ()
{
dictionary.AddWord ("Hello");
Assert.AreEqual ("Hello: 1", dictionary.ShowContents ());
}
并且显然期望 return 值而不是输出到控制台的内容。我在这里的其他地方读到,没有必要测试 Console.WriteLine,因为你只是假设它有效,所以你可以在这个方法中使用 return,然后编写另一个只写入控制台的方法(和因此不需要测试)。这个问题是a)我不知道如何编写一个returns所有键和值的方法; b) 我不是 return 一个东西,而是许多不同的字符串。
关于我如何处理这件事有什么建议吗?
您可以编写一个函数来return ShowContents
输出的整个字符串;类似于:
public string GetContents()
{
var sb = new StringBuilder();
foreach (KeyValuePair<string, int> item in dictionary) {
sb.AppendLine(string.Format("{0}: {1}", item.Key, item.Value));
}
return sb.ToString();
}
那么你的ShowContents
就是:
Console.Write(GetContents());
并且您可以测试 GetContents
return 是否符合您的预期,而无需涉及 Console.WriteLine
。
虽然您已经接受了 Blorgbeard 的回答(在这种情况下显然完全有效),但我想在您的问题中加上我的两分钱。
据我了解,你必须测试你想要实现的行为。实际上,问题和答案之间的变化使测试从 "I want to test that this method writes all values to a text reader" 变为 "I want to test that this method returns all values concatenated"。您不再测试书写行为,而是格式化行为。
在您的情况下,此更改不是问题,但可能会有问题。例如,假设您想将一大组数据写入流。您可能希望一段一段地编写它,以免将整个数据加载到内存中。如果您测试连接的字符串输出,您的测试可能会通过(如果您不使用完整的数据集,这在测试中通常不会使用)并且在生产中会失败,因为数据太多。
无论如何,您可以通过传递给方法 a TextWriter
来测试写入行为。然后在您的测试中,您可以传递自定义 TextWriter
来检查写入的数据。在您的生产代码中,您将传递 Console.Out
以写入控制台。
public void ShowContents (TextWriter writer)
{
foreach (KeyValuePair<string, int> item in dictionary) {
writer.WriteLine ("{0}: {1}", item.Key, item.Value);
}
}
// calling in production code
ShowContents(Console.Out);
如果您想为测试准备 Console
而不是通过 TextWriter
,也可以使用 Console.SetOut
方法。您可以在 Mark Seeman 的 this article 中找到更多信息。我真的不喜欢更改控制台的输出,因为我不喜欢该方法写入静态文本编写器。没有告诉您该函数写入标准输出,所以我更喜欢将 TextWriter 作为参数传递
我正在尝试使用 TDD 在 C# 中编写一个控制台应用程序(我对此非常陌生)。
我正在尝试遍历包含字符串作为键和整数作为值的字典,并将它们作为 "key: value" 输出到控制台。我尝试了很多不同的东西,终于找到了一些可能有用的东西:
public void ShowContents ()
{
foreach (KeyValuePair<string, int> item in dictionary) {
Console.WriteLine ("{0}: {1}", item.Key, item.Value);
}
}
我遇到的问题是 - 我不知道如何测试它。我的测试目前看起来像这样:
[Test ()]
public void CanShowContentsOfDictionary ()
{
dictionary.AddWord ("Hello");
Assert.AreEqual ("Hello: 1", dictionary.ShowContents ());
}
并且显然期望 return 值而不是输出到控制台的内容。我在这里的其他地方读到,没有必要测试 Console.WriteLine,因为你只是假设它有效,所以你可以在这个方法中使用 return,然后编写另一个只写入控制台的方法(和因此不需要测试)。这个问题是a)我不知道如何编写一个returns所有键和值的方法; b) 我不是 return 一个东西,而是许多不同的字符串。
关于我如何处理这件事有什么建议吗?
您可以编写一个函数来return ShowContents
输出的整个字符串;类似于:
public string GetContents()
{
var sb = new StringBuilder();
foreach (KeyValuePair<string, int> item in dictionary) {
sb.AppendLine(string.Format("{0}: {1}", item.Key, item.Value));
}
return sb.ToString();
}
那么你的ShowContents
就是:
Console.Write(GetContents());
并且您可以测试 GetContents
return 是否符合您的预期,而无需涉及 Console.WriteLine
。
虽然您已经接受了 Blorgbeard 的回答(在这种情况下显然完全有效),但我想在您的问题中加上我的两分钱。
据我了解,你必须测试你想要实现的行为。实际上,问题和答案之间的变化使测试从 "I want to test that this method writes all values to a text reader" 变为 "I want to test that this method returns all values concatenated"。您不再测试书写行为,而是格式化行为。
在您的情况下,此更改不是问题,但可能会有问题。例如,假设您想将一大组数据写入流。您可能希望一段一段地编写它,以免将整个数据加载到内存中。如果您测试连接的字符串输出,您的测试可能会通过(如果您不使用完整的数据集,这在测试中通常不会使用)并且在生产中会失败,因为数据太多。
无论如何,您可以通过传递给方法 a TextWriter
来测试写入行为。然后在您的测试中,您可以传递自定义 TextWriter
来检查写入的数据。在您的生产代码中,您将传递 Console.Out
以写入控制台。
public void ShowContents (TextWriter writer)
{
foreach (KeyValuePair<string, int> item in dictionary) {
writer.WriteLine ("{0}: {1}", item.Key, item.Value);
}
}
// calling in production code
ShowContents(Console.Out);
如果您想为测试准备 Console
而不是通过 TextWriter
,也可以使用 Console.SetOut
方法。您可以在 Mark Seeman 的 this article 中找到更多信息。我真的不喜欢更改控制台的输出,因为我不喜欢该方法写入静态文本编写器。没有告诉您该函数写入标准输出,所以我更喜欢将 TextWriter 作为参数传递