为什么 .NET (Core) 中的大多数 mock 框架都不能 mock static 和 private 方法?
Why can most of the mock frameworks in .NET (Core) not mock static and private methods?
我的问题是关于此限制的技术原因,而不是关于如何修复它。
为什么有些框架像Telerik JustMock and Typemock Isolator support these features, but we can not have these in Moq or FakeItEasy or NSubstitute等?
提到的项目在单元测试中是否不必要?
这是因为这些库的工作方式。当您使用 Moq、NSubstitute 或 FakeItEasy 模拟 class 时,它们会动态创建一个 class,它继承自该 class 并覆盖其方法。但是他们必须遵循平台的重写方法规则:
- non-virtual 方法不能被覆盖,根据定义
- 私有方法不能被派生的 classes 访问,所以它们不能被覆盖(事实上,C# 甚至不允许它们是虚拟的,因为它没有意义)
- 静态方法也不能被覆盖,因为它没有意义:多态性基于您调用方法的实例类型,而静态方法没有实例...
事实上,这些模拟库不会做任何你自己手动编写 fake/mock classes 无法完成的事情;他们只是通过让您摆脱样板代码而变得更容易。您不能手动覆盖静态或 non-virtual 方法,出于同样的原因,这些库也不能这样做。
不知道JustMock和TypeMock Isolator是怎么工作的;我怀疑他们对 CLR 的内部结构施了一些黑魔法,或者可能会动态重写代码(这就是 Pose 所做的:它将对指定方法的调用替换为对替换方法的调用)。
编辑:参见this question about how TypeMock Isolator works。它使用探查器 API 劫持方法调用。正如我所说,黑魔法^^
我的问题是关于此限制的技术原因,而不是关于如何修复它。
为什么有些框架像Telerik JustMock and Typemock Isolator support these features, but we can not have these in Moq or FakeItEasy or NSubstitute等?
提到的项目在单元测试中是否不必要?
这是因为这些库的工作方式。当您使用 Moq、NSubstitute 或 FakeItEasy 模拟 class 时,它们会动态创建一个 class,它继承自该 class 并覆盖其方法。但是他们必须遵循平台的重写方法规则:
- non-virtual 方法不能被覆盖,根据定义
- 私有方法不能被派生的 classes 访问,所以它们不能被覆盖(事实上,C# 甚至不允许它们是虚拟的,因为它没有意义)
- 静态方法也不能被覆盖,因为它没有意义:多态性基于您调用方法的实例类型,而静态方法没有实例...
事实上,这些模拟库不会做任何你自己手动编写 fake/mock classes 无法完成的事情;他们只是通过让您摆脱样板代码而变得更容易。您不能手动覆盖静态或 non-virtual 方法,出于同样的原因,这些库也不能这样做。
不知道JustMock和TypeMock Isolator是怎么工作的;我怀疑他们对 CLR 的内部结构施了一些黑魔法,或者可能会动态重写代码(这就是 Pose 所做的:它将对指定方法的调用替换为对替换方法的调用)。
编辑:参见this question about how TypeMock Isolator works。它使用探查器 API 劫持方法调用。正如我所说,黑魔法^^