单元测试私有代码

Jas*_*son 15 c# testing methods tdd private

我目前正在使用C#进行开发 - 这里有一些背景知识:我们用我们的客户端应用程序实现MVP,并且我们有一个循环规则,它规定没有方法应该具有大于5的圈复杂度.这会导致许多小的私有方法这通常是一件事.

我的问题是关于单元测试一个类:

通过公共方法测试私有实现都很好......我没有遇到实现这个问题的问题.

但是......以下情况如何:

示例1.处理异步数据检索请求的结果(回调方法不应仅供公开测试)

示例2.执行操作的事件处理程序(例如更新View标签的文本 - 我知道的愚蠢示例......)

示例3.您正在使用第三方框架,该框架允许您通过覆盖受保护的虚拟方法进行扩展(从公共方法到这些虚拟方法的路径通常被视为黑盒编程,并且将具有框架提供的各种依赖性你不想知道)

上面的例子在我看来并不是设计不佳的结果.他们似乎也没有成为单独进行单独测试的候选人,因为这样的方法会失去他们的背景.

没有人对此有任何想法吗?

干杯,杰森

编辑: 我认为我在原始问题中不够清楚 - 我可以使用访问器测试私有方法,并使用TypeMock模拟调用/方法.那不是问题.问题是测试不需要公开或不公开的东西.

我不想为了测试而公开代码,因为它可能会引入安全漏洞(只发布一个接口来隐藏它不是一个选项,因为任何人都可以将对象强制转换回其原始类型并获取访问权限我不希望他们)

被重构到另一个类进行测试的代码很好 - 但可能会失去上下文.我一直认为让'辅助'类可以包含一堆没有特定上下文的代码是不好的做法 - (在这里思考SRP).我真的不认为这适用于事件处理程序.

我很高兴被证明是错的 - 我只是不确定如何测试这个功能!我一直认为,如果它可以破坏或改变 - 测试它.

干杯,杰森

Mat*_*att 15

正如克里斯所说,标准做法只是对公共方法进行单元测试.这是因为,作为该对象的消费者,您只关心公开可用的内容.而且,理论上,使用边缘情况进行适当的单元测试将充分运用他们拥有的所有私有方法依赖性.

话虽如此,我发现有几次直接针对私有方法编写单元测试非常有用,并且通过单元测试最简洁地解释一些可能遇到的更复杂的场景或边缘情况.

如果是这种情况,您仍然可以使用反射调用私有方法.

MyClass obj = new MyClass();
MethodInfo methodInfo = obj.GetType().GetMethod("MethodName", BindingFlags.Instance | BindingFlags.NonPublic);
object result = methodInfo.Invoke(obj, new object[] { "asdf", 1, 2 });
// assert your expected result against the one above
Run Code Online (Sandbox Code Playgroud)


Tru*_*ill 7

我们有一个圈数规则,它规定任何方法都不应该具有大于5的圈复杂度

我喜欢这个规则.

关键是私有方法是实现细节.它们可能会发生变化/重构.您想测试公共接口.

如果您有具有复杂逻辑的私有方法,请考虑将它们重构为单独的类.这也可以帮助减少圈复杂度.另一个选择是使方法内部并使用InternalsVisibleTo(在Chris的答案中的一个链接中提到).

当您在私有方法中引用外部依赖项时,捕获往往会进入.在大多数情况下,您可以使用依赖注入等技术来分离类.对于使用第三方框架的示例,这可能很困难.我首先尝试重构设计以分离第三方依赖项.如果无法做到这一点,请考虑使用Typemock Isolator.我没有使用它,但它的关键功能是能够"模拟"私有,静态等方法.

类是黑盒子.以这种方式测试它们.

编辑:我会尝试回应杰森对我的答案和原始问题的编辑的评论.首先,我认为SRP推动更多的类,从他们身上没有离开.是的,最好避免使用瑞士军队的帮助班.但是设计用于处理异步操作的类呢?还是数据检索类?这些部分是原始课程的责任,还是可以分开?

例如,假设您将此逻辑移动到另一个类(可能是内部的).该类实现了一个异步设计模式,允许调用者选择是同步还是异步调用该方法.单元测试或集成测试是针对同步方法编写的.异步调用使用标准模式,复杂度低; 我们不测试那些(验收测试除外).如果异步类是内部的,请使用InternalsVisibleTo来测试它.

  • 感谢答案 - 我应该提到我确实使用了TypeMock Isolator,并且模拟了类,方法类不是问题.也没有处理私有代码问题.有什么问题是(举例1)如果我嘲笑执行数据回溯的类 - 我不能让它调用回调.(示例2)我无法在不深入研究类的私有方法的情况下测试私有事件处理程序. (2认同)

Chr*_*ris 3

在我所有的单元测试中,我从来没有费心测试private功能。我通常只是测试public功能。这与黑盒测试方法一致。

您是对的,除非公开私有类,否则您确实无法测试私有函数。

如果您的“用于测试的单独类”位于同一个程序集中,您可以选择使用内部而不是私有。这会将内部方法公开给您的代码,但程序集中以外的代码将无法访问这些方法。

编辑: 搜索这个主题时我遇到了这个问题。投票最多的答案与我的答案类似。

  • 啊,但你实际上可以测试私有类:)。应该在“但是我应该吗?”下提交,但实际上这是可能的。在某些情况下我发现它很有用。 (2认同)