图案的名称是什么?
我经常设计系统,其中我的系统中有一个类,它有一堆受保护的方法。受保护的方法是因为它们应该可供专业化访问,因此,我认为受保护的方法是我的通用类和任何专用类之间的契约。
因此,我想测试这些方法的行为是否正确,因此我的单元测试将需要访问受保护的方法,这在 C# 中是不可能的,除非使用像反射这样的肮脏黑客。
我通常选择的解决方案是在单元测试中创建一个专门的类,将这些受保护的方法公开为公共方法。因为我总是将单元测试保存在单独的程序集中,所以系统代码本身无法访问这些类,并且在我的系统代码内,受保护的函数仍然受到保护。
// In the system code assembly
namespace MySystem {
public class SomeClass {
protected void DoSomething() {
...
}
}
}
// In the unit test assembly
namespace MySystem.Unittests {
public class SomeClass2 : SomeClass {
public new void DoSomething() {
base.DoSomething();
}
}
}
我的单元测试现在能够通过实例化专用类来测试父类上受保护成员的行为。
我还进一步使用它来模拟对象并模拟对受保护虚拟函数的函数调用,但该代码有点复杂,所以我将其删除。
我发现完成这项任务的这种方式是如此直接,以至于我不可能是唯一这样做的人,所以我认为必须有一个共同的命名约定?
I often design system where I have a class in my system that has a bunch of protected methods. The protected methods are that because they should be accessible to specializations, and as such, I consider the protected methods to be a contract between my general class and any specialized classes.
Therefore I want to test that these methods behave correctly, so my unit tests will need to access the protected methods, something that is not possible in c#, except by using dirty hacks like reflection.
The solution I normally choose is that I create a specialized class inside my unit test that exposes these protected methods as public. Because I always keep the unit tests in a separate assembly, the system code itself does not have access to these classes, and inside my system code, the protected function remains protected.
// In the system code assembly
namespace MySystem {
public class SomeClass {
protected void DoSomething() {
...
}
}
}
// In the unit test assembly
namespace MySystem.Unittests {
public class SomeClass2 : SomeClass {
public new void DoSomething() {
base.DoSomething();
}
}
}
My unit test is now able to test the behaviour of the protected member on the parent class by instantiating the specialized class.
I also use this even further to be able to mock the object and mock function calls to protected virtual functions, but that code is a little more complex, so I'll just cut that out.
I find this way of accomplishing this task to be so straight forward that I cannot possibly be the only person doing this, and so I assume that there must be a common naming convention for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我只在我无法控制需要测试的类时才这样做。 Charles 指出当您控制源代码时您可以在 .NET 中做什么。
您的情况有点不同,因为您的类旨在用作超类,因此通过子类测试它很有意义(因为该类并不打算独立存在)。在这种情况下,您基本上是在执行 测试特定子类 的变体。链接中描述的模式更多的是关于覆盖行为,如果您有一个没有首先编写测试并且具有高耦合的类,那么它非常有用,这是梳理依赖关系的好方法(通常作为中间步骤)获取作为参数传递的单独的类)。在您的情况下,“压倒一切”的目的是增加访问权限,但它似乎符合相同的模式。
I have only done this when I don't control the class needed to be tested. Charles points out what you can do in .NET when you control the source code.
Your case is a bit different in that your class is intended to be used as a superclass, so testing it via a subclass makes a lot of sense (since the class isn't intended to stand on its own). In this case, you are basically doing a variant of Test-Specific Subclass. The pattern described in the link is more about overriding behavior, and is very useful if you have a class that was not written test first and has a high coupling, it is a good way to tease apart the dependency (usually as an intermediate step to getting a separate class passed as a parameter). In your case, the "overriding" is for the purpose if increasing access, but it seems to fit the same pattern.
我不确定我是否明白测试受保护方法的意义,尽管我是从 TDD 的角度来看的。一般来说,您的测试是针对类的公共方法编写的。当您重构代码以提取内部使用的通用方法时,就会出现受保护的方法。由于这些是由重构引起的,因此您现有的测试已经涵盖了正在重构的代码。稍后对通过专业化的公共方法使用重构方法的代码进行的测试也会测试代码——在这种情况下,专业化的公共方法在使用公共的受保护方法时可以正常工作。
在少数情况下,对受保护方法进行显式测试是有意义的,我不认为使用反射来进行测试有什么坏处。毕竟,您只是为了测试的目的而破坏封装。
I'm not sure that I see the point, generally, in testing your protected methods, though, I'm speaking from a TDD point of view. Generally, your tests are written against the public methods of the class. Protected methods arise as you refactor code to extract common methods that are used internally. Since these arise from refactorings, your existing tests already cover the code being refactored. Later tests for code that uses the refactored methods via the public methods of specializations also test the code -- in this case that the public methods of the specialization work properly when using the common, protected methods.
In the few cases where an explicit test for a protected method makes sense, I don't see the harm in using reflection to conduct the test. You're only breaking encapsulation for the purpose of the test after all.
不知道你正在做的事情的模式名称,但是 .net 有一个解决方案...将方法设置为受保护的内部,然后将以下内容添加到项目的 assemblyInfo 文件中
这将使项目中的内部方法对于属性中指定的测试程序集可见
Don't know of a pattern name for whaty you are doing, but .net has a solution for this... Make the methods protected internal, and then add the following to the projects assemblyInfo file
This will make the internal methods in the project visible to the test assembly specified in the attribute
我想在这里提到另一种模式,因为它是测试特定子类的特例。据我所知,它没有自己的名称:让测试用例扩展被测类。示例:
当然,只有在 SomeClass 有无参数构造函数的情况下,这才有效。
There is another pattern that I want to mention here, because it is a special case of the Test-Specific Subclass. It does not have its own name as far as I know: Having the Test Case extend the class under test. Example:
This does only work, if SomeClass has a parameterless Constructor, of course.