2

我正在尝试使用 TDD 在 C# 中编写一个控制台应用程序(我很新)。

我正在尝试遍历包含字符串作为键和整数作为值的字典,并将它们作为“键:值”输出到控制台。我尝试了很多不同的东西,最后找到了一些可能有用的东西:

    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 ());
    }

并且显然期望返回值而不是输出到控制台的东西。我在这里的其他地方读到,没有必要对 Console.WriteLine 进行测试,因为您只是假设它有效,因此您可以在此方法中使用 return ,然后编写另一个仅写入控制台的方法(因此不需要进行测试)。问题在于 a) 我不知道如何编写一个返回所有键和值的方法;b)我不是返回一件事,而是返回许多不同的字符串。

关于我如何解决这个问题的任何建议?

4

2 回答 2

3

您可以编写一个函数来返回由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返回您期望的结果,而不涉及Console.WriteLine.

于 2015-03-29T22:34:42.883 回答
1

尽管您已经接受了 Blorgbeard 的回答(在这种情况下显然是完全有效的),但我想在您的问题中加上两分钱。

据我了解,您必须测试您想要实现的行为。实际上,您的问题和答案之间的变化使测试从“我想测试此方法是否将所有值写入文本阅读器”变为“我想测试此方法是否返回所有连接的值”。您不再测试一种书写行为,而是一种格式化行为。

在您的情况下,此更改不是问题,但可能会出现问题。例如,假设您想将一大组数据写入流。您可能希望逐个编写它,以免将整个数据加载到内存中。如果您测试连接的字符串输出,您的测试可能会通过(如果您不使用完整的数据集,通常不会在测试中使用)并且由于数据太多而在生产中失败。

无论如何,您可以通过传递给方法 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.SetOutConsole为您的测试做准备而不是通过TextWriter. 您可以在Mark Seeman的这篇文章中找到更多信息。我不太喜欢更改控制台的输出,因为我不喜欢该方法写入静态文本编写器。没有什么告诉您该函数写入标准输出,所以我更喜欢将 TextWriter 作为参数传递

于 2015-03-30T09:10:58.743 回答