如何对使用私有 属性 的 public 方法进行单元测试?
How do I unit test a public method which utilizes a private property?
我有一个 class,它基本上是一个管道。它处理消息,然后批量删除它们。为了做到这一点,ProcessMessage()
方法不会直接删除消息;它将它们添加到私有 Observable<IMessage>()
。然后我有另一个 public 方法,它监视可观察的并删除消息。
这导致代码类似于:
public void CreateDeletionObservable(int interval = 30, int messageCount = 10)
{
this.processedMessages.Buffer(TimeSpan.FromSeconds(interval), messageCount).Subscribe(observer =>
{
client.Value.DeleteMessages(observer.ToList());
});
}
问题是我的单元测试没有 processedMessages
的值。我无法提供最小起订量的价值,因为它是私人的。我不需要测试 processedMessages 中的值;我只需要它们存在即可测试该方法的行为。具体来说,我需要测试我的可观察对象是否会在抛出异常时继续 运行(该逻辑尚未在代码中)。在我看来,我有几个选择:
1) 重构我的 class 以使用具有单个入口点和几个出口点(成功、错误、重试等)的单个怪物可观察链。 将 避免使用私有属性在 public 方法之间传递集合。但是,该链极难解析,更不用说单元测试了。我不认为降低我的代码的可读性和可测试性是一个可行的选择。
2) 修改我的 CreateDeletionObservable
方法以接受消息测试列表:
public void CreateDeletionObservable(int interval = 30, int messageCount = 10, IObservable<IMessage> processedMessages = null)
这将允许我为要使用的方法提供存根数据,但这是一种可怕的代码味道。对此的一种变体是在构造函数级别注入 Observable,但这也好不到哪里去。可能更糟。
3) 使processedMessages
public。
4) 不要测试此功能。
我不喜欢这些选项中的任何一个,但我倾向于 2;为测试目的注入一个列表。我在这里缺少一个选项吗?
你的感觉很好。我认为在这种情况下,您可以恢复到我认为有用的指导 "Test your boundaries"(Udi Dahan,但找不到参考)。
您似乎可以输入消息(通过 Observable 序列),作为副作用,您最终会从客户端删除这些消息。所以看起来你的测试应该是
- "Given an EventProcessor, When 10 Messages are Processed, Then the Events are deleted from the client"
- "Given an EventProcessor, When 5 Messages are Processed in 30s, Then the Events are deleted from the client"
因此,与其测试以某种方式知道 this.processedMessages
(该实例从何而来?)的这一小部分管道,不如测试链。但这并不意味着您需要创建一个庞大的无法使用的链。只需创建足够的链以使其可测试。
提供更多的代码库也会有所帮助,例如this.processedMessages
& client.Value
从哪里来?这可能是关键,并且猜测应用更实用的方法可能会有所帮助?
我有一个 class,它基本上是一个管道。它处理消息,然后批量删除它们。为了做到这一点,ProcessMessage()
方法不会直接删除消息;它将它们添加到私有 Observable<IMessage>()
。然后我有另一个 public 方法,它监视可观察的并删除消息。
这导致代码类似于:
public void CreateDeletionObservable(int interval = 30, int messageCount = 10)
{
this.processedMessages.Buffer(TimeSpan.FromSeconds(interval), messageCount).Subscribe(observer =>
{
client.Value.DeleteMessages(observer.ToList());
});
}
问题是我的单元测试没有 processedMessages
的值。我无法提供最小起订量的价值,因为它是私人的。我不需要测试 processedMessages 中的值;我只需要它们存在即可测试该方法的行为。具体来说,我需要测试我的可观察对象是否会在抛出异常时继续 运行(该逻辑尚未在代码中)。在我看来,我有几个选择:
1) 重构我的 class 以使用具有单个入口点和几个出口点(成功、错误、重试等)的单个怪物可观察链。 将 避免使用私有属性在 public 方法之间传递集合。但是,该链极难解析,更不用说单元测试了。我不认为降低我的代码的可读性和可测试性是一个可行的选择。
2) 修改我的 CreateDeletionObservable
方法以接受消息测试列表:
public void CreateDeletionObservable(int interval = 30, int messageCount = 10, IObservable<IMessage> processedMessages = null)
这将允许我为要使用的方法提供存根数据,但这是一种可怕的代码味道。对此的一种变体是在构造函数级别注入 Observable,但这也好不到哪里去。可能更糟。
3) 使processedMessages
public。
4) 不要测试此功能。
我不喜欢这些选项中的任何一个,但我倾向于 2;为测试目的注入一个列表。我在这里缺少一个选项吗?
你的感觉很好。我认为在这种情况下,您可以恢复到我认为有用的指导 "Test your boundaries"(Udi Dahan,但找不到参考)。
您似乎可以输入消息(通过 Observable 序列),作为副作用,您最终会从客户端删除这些消息。所以看起来你的测试应该是
- "Given an EventProcessor, When 10 Messages are Processed, Then the Events are deleted from the client"
- "Given an EventProcessor, When 5 Messages are Processed in 30s, Then the Events are deleted from the client"
因此,与其测试以某种方式知道 this.processedMessages
(该实例从何而来?)的这一小部分管道,不如测试链。但这并不意味着您需要创建一个庞大的无法使用的链。只需创建足够的链以使其可测试。
提供更多的代码库也会有所帮助,例如this.processedMessages
& client.Value
从哪里来?这可能是关键,并且猜测应用更实用的方法可能会有所帮助?