[英]static methods and unit tests
I've been reading that static methods tend to be avoided when using TDD because they tend to be hard to mock. 我一直在读,使用TDD时往往会避免使用静态方法,因为它们往往难以模拟。 I find though, that the easiest thing to unit test is a static method that has simple functionality. 我发现,单元测试最简单的方法是一个具有简单功能的静态方法。 Don't have to instantiate any classes, encourages methods that a simple, do one thing, are "standalone" etc. 不必实例化任何类,鼓励简单,做一件事,“独立”等方法。
Can someone explain this discrepancy between TDD best practices and pragmatic ease? 有人可以解释TDD最佳实践和务实轻松之间的差异吗?
thanks, A 谢谢
A static method is easy to test, but something that directly calls a static method generally is not easy to test independent of the static method it depends on. 静态方法很容易测试,但直接调用静态方法的东西通常不容易独立于它依赖的静态方法进行测试。 With a non-static method you can use a stub/mock/fake instance to ease testing, but if the code you're testing calls static methods it's effectively "hard-wired" to that static method. 使用非静态方法,您可以使用存根/模拟/假实例来简化测试,但如果您正在测试的代码调用静态方法,则它实际上与该静态方法“硬连线”。
The answer to the asked question is, in my opinion "Object Oriented seems to be all that TDD people think about." 问题的答案是,在我看来,“面向对象似乎是TDD人们所想的全部内容”。
Why? 为什么? I don't know. 我不知道。 Maybe they are all Java programmers who've been infected with the disease of making everything rely on six indirection layers, dependency injection and interface adapters. 也许他们都是Java程序员,他们已经感染了使一切依赖于六个间接层,依赖注入和接口适配器的疾病。
Java programmers seem to love to make everything difficult up front in order to "save time later." Java程序员似乎喜欢预先让一切变得困难,以“以后节省时间”。
I advise applying some Agile principles to your TDD: If it isn't causing a problem then don't fix it. 我建议将一些敏捷原则应用到您的TDD:如果它没有引起问题,那么不要修复它。 Don't over design. 不要过度设计。
In practice I find that if the static methods are tested well first then they are not going to be the cause of bugs in their callers. 在实践中,我发现如果首先测试静态方法,那么它们不会成为调用者中的错误的原因。
If the static methods execute quickly then they don't need a mock. 如果静态方法快速执行,那么它们不需要模拟。
If the static methods work with stuff from outside the program, then you might need a mock method. 如果静态方法使用程序外部的东西,那么您可能需要一个模拟方法。 In this case you'd need to be able to simulate many different kinds of function behavior. 在这种情况下,您需要能够模拟许多不同类型的函数行为。
If you do need to mock a static method remember that there are ways to do it outside of OO programming. 如果你确实需要模拟一个静态方法,请记住在 OO编程之外有办法做到这一点。
For example, you can write scripts to process your source code into a test form that calls your mock function. 例如,您可以编写脚本来将源代码处理为调用mock函数的测试表单。 You could link different object files that have different versions of the function into the test programs. 您可以将具有不同版本功能的不同目标文件链接到测试程序中。 You could use linker tricks to override the function definition (if it didn't get inlined). 您可以使用链接器技巧来覆盖函数定义(如果它没有内联)。 I am sure there are some more tricks I haven't listed here. 我相信还有一些我没有在这里列出的技巧。
It's easy to test the static method. 测试静态方法很容易。 The problem is that there is no way to isolate your other code from that static method when testing the other code. 问题是在测试其他代码时无法将其他代码与静态方法隔离开来。 The calling code is tightly-coupled to the static code. 调用代码与静态代码紧密耦合。
A reference to a static method cannot be mocked by many mocking frameworks nor can it be overridden. 静态方法的引用不能被许多模拟框架嘲笑,也不能被覆盖。
If you have a class that is making lots of static calls, then to test it you have to configure the global state of the application for all of those static calls - so maintenance becomes a nightmare. 如果你有一个正在进行大量静态调用的类,那么要测试它,你必须为所有这些静态调用配置应用程序的全局状态 - 因此维护变成了一场噩梦。 And if your test fails, then you don't know which bit of code caused the failure. 如果您的测试失败,那么您不知道哪个位代码导致了失败。
Getting this wrong, is one of the reasons that many developers think TDD is nonsense. 弄错了,是许多开发人员认为TDD无意义的原因之一。 They put in a huge maintenance effort for test results that only vaguely indicate what went wrong. 他们为测试结果付出了巨大的维护费用,只是模糊地指出出了什么问题。 If they'd only reduced the coupling between their units of code, then maintenance would be trivial and the test results specific. 如果他们只减少了他们的代码单元之间的耦合,那么维护将是微不足道的,并且测试结果是特定的。
That advice is true for the most part.. but not always. 这个建议在大多数情况下都是正确的......但并非总是如此。 My comments are not C++ specific.. 我的评论不是C ++特有的..
Lets take an example 让我们举个例子
public class MyStaticClass
{
static int __count = 0;
public static int GetAddCount()
{ return ++__count; }
public static int Add(int operand1, int operand2)
{ return operand1 + operand2; }
// needed for testability
internal static void ResetCount()
{
__count = 0;
}
}
...
//test1
MyStaticClass.Add(2,3); // => 5
MyStaticClass.GetAddCount(); // => 1
// test2
MyStaticClass.Add(2,3); // => 5
//MyStaticClass.ResetCount(); // needed for tests
MyStaticClass.GetAddCount(); // => unless Reset is done, it can differ from 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.