如何对使用私有财产的公共方法进行单元测试?

时间:2016-12-07 18:22:29

标签: c# unit-testing system.reactive

我有一个基本上是管道的类。它处理消息,然后批量删除它们。为此,ProcessMessage()方法不直接删除消息;它将它们添加到私人Observable<IMessage>()。然后我有另一个公共方法,它监视可观察的并且整体删除消息。

这导致代码类似于:

public void CreateDeletionObservable(int interval = 30, int messageCount = 10)
{
    this.processedMessages.Buffer(TimeSpan.FromSeconds(interval), messageCount).Subscribe(observer =>
    {
        client.Value.DeleteMessages(observer.ToList());
    });
}

问题是我的单元测试没有processedMessages的值。我不能提供moq'd值,因为它是私有的。我不需要测试processedMessages中的值;我只需要它们存在就可以测试该方法的行为。具体来说,我需要测试我的observable是否会在抛出异常时继续运行(该逻辑不在代码中)。在我看来,我有几个选择:

1)重构我的类以使用单个怪物可观察链,其具有单个入口点和几个出口(成功,错误,重试等)。此避免使用私有属性在公共方法之间传递集合。但是,这个链很难解析更少的单元测试。我不相信让我的代码不那么可读和可测试是一个可行的选择。

2)修改我的CreateDeletionObservable方法以接受消息的测试列表:

    public void CreateDeletionObservable(int interval = 30, int messageCount = 10, IObservable<IMessage> processedMessages = null)

这将允许我为使用的方法提供存根数据,但这是一种可怕的代码味道。对此的一个变化是在构造函数级别注入Observable,但这并不是更好。可能更糟。

3)公开processedMessages

4)不要测试此功能。

我不喜欢这些选项,但我倾向于2;为测试目的注入列表。我在这里找不到一个选项吗?

1 个答案:

答案 0 :(得分:1)

你的感官很好。我想在这种情况下你可以回到我发现有用的指导&#34;测试你的界限&#34; (Udi Dahan,但无法找到参考)。

您似乎可以输入消息(通过Observable Sequence),并且作为副作用,您最终将从客户端删除这些消息。因此,您的测试似乎应该读取类似

的内容
  • &#34;给定一个EventProcessor,当处理10个消息时,然后从客户端删除事件&#34;
  • &#34;给定一个EventProcessor,当30s内处理5个消息时,然后从客户端删除事件&#34;

所以不要测试管道的这个小部分,而是以某种方式知道this.processedMessages(该实例来自哪里?),测试链。但这并不意味着您需要创建一个庞大的无法使用的链。只需创建足够的链以使其可测试。

提供更多代码库也会有所帮助,例如: this.processedMessages&amp; client.Value来自哪里?这可能是关键,并且猜测应用更实用的方法可能会有所帮助吗?