测试我是否可以遍历字典并将键和值写入控制台

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 作为参数传递