java 单元测试辅助方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1861338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unit test helper methods?
提问by Aly
I have classes which previously had massive methods so I subdivided the work of this method into 'helper' methods.
我有以前有大量方法的类,所以我将此方法的工作细分为“帮助”方法。
These helper methods are declared privateto enforce encapsulation - however I want to unit test the big public methods. Is it good to unit test the helper methods too as if one of them fail the public method that calls it will also fail, and this way we can identify why it failed?
这些辅助方法被声明private为强制封装 - 但是我想对大型公共方法进行单元测试。是否也可以对辅助方法进行单元测试,好像其中一个失败,调用它的公共方法也将失败,这样我们就可以确定失败的原因?
Also in order to test these using a mock object I would need to change their visibility from private to protected, is this desirable?
此外,为了使用模拟对象测试这些,我需要将它们的可见性从私有更改为受保护,这是可取的吗?
采纳答案by Aaron Digulla
One way is to omit privateand put the tests in the same package. Then the tests can call the internal methods but no one else (= outside the package) can.
一种方法是省略private测试并将其放在同一个包中。然后测试可以调用内部方法,但没有其他人(= 包外)可以。
Also, failing internal methods should produce error messages which make it easy to fix the issue. When you put the code into production, you'll see less than the tests and you'll be under a lot of pressure to fix the issues fast. So one minute spent here will save you one hour later with your boss sitting in your neck.
此外,失败的内部方法应该会产生错误消息,从而可以轻松解决问题。当您将代码投入生产时,您会看到比测试更少的内容,并且您将承受很大的压力来快速解决问题。因此,在这里花一分钟可以节省一小时后老板坐在你脖子上的时间。
回答by VoiceOfUnreason
This smells like you have the wrong problem. What you've described is akin to creating a sub-"unit test", which leads me to believe that your unit tests are really testing a unit after all.
这听起来像你有错误的问题。你所描述的类似于创建一个子“单元测试”,这让我相信你的单元测试毕竟真的是在测试一个单元。
Which is not a criticism of what you are trying to do: going from "where we are today" to "somewhere else that's measurably better" is a winning move. However, it is a suggestion that you step back a bit to evaluate where you are - understanding how your current situation differs from some Platonic ideal could help to show new possibilities.
这不是对您正在尝试做的事情的批评:从“我们今天所处的位置”到“其他明显更好的地方”是一个成功的举动。但是,建议您退后一步以评估您所处的位置 - 了解您当前的情况与某些柏拉图式的理想有何不同有助于展示新的可能性。
There are plenty of suggestions here about scoping your helper methods. Another possibility would be to review the implementation to determine if there are helper classes lurking in your current implementation. Creating a new class and a suite of tests to exercise it is always acceptable.
这里有很多关于确定辅助方法范围的建议。另一种可能性是检查实现以确定当前实现中是否潜伏着帮助程序类。创建一个新类和一套测试来练习它总是可以接受的。
Note that this approach insulates you from the refactoring: you can change the implementation without changing your test suite (because the unit tests for the helper object continue to pass even when the helper object is no longer part of your production implementation), and you get a clean packaging of the implementation and the tests for it (usecase: you decide that bozo-sort is the wrong implementation, and should no longer be used. If the bozo-sort implementation is isolated, then you simply remove it and its tests. But when the tests of the bozo-sort implementation are tangled with all of the other tests, there's more thinking involved).
请注意,这种方法将您与重构隔离开来:您可以在不更改测试套件的情况下更改实现(因为即使助手对象不再是生产实现的一部分,助手对象的单元测试也会继续通过),并且您会得到实现及其测试的干净包装(用例:您认为 bozo-sort 是错误的实现,不应再使用。如果 bozo-sort 实现是孤立的,那么您只需删除它及其测试。但是当 bozo-sort 实现的测试与所有其他测试纠缠在一起时,就会涉及更多的思考)。
It may also help to review why you have unit tests for your code. If one of the reasons is "to make refactoring safe", then you don't want to be writing tests that lock you into an implementation.
检查为什么对代码进行单元测试也可能会有所帮助。如果原因之一是“使重构安全”,那么您不希望编写将您锁定在实现中的测试。
回答by Steve Freeman
If your class really is that big, then it sounds like you should be breaking out helper objects, not just helper methods(although extracting methods is often a step along the way). Once you've done that, your old class becomes simpler and easier to test (perhaps with mocks, perhaps not), and you can test the methods on the new supporting classes directly.
如果你的类真的那么大,那么听起来你应该打破辅助对象,而不仅仅是辅助方法(尽管提取方法通常是一个过程)。一旦你这样做了,你的旧类就会变得更简单、更容易测试(也许用模拟,也许不是),你可以直接在新的支持类上测试方法。
My preference is to test through the public API of an object. If that's too hard, then it's a hint that the object should be broken up.
我的偏好是通过对象的公共 API 进行测试。如果这太难了,则暗示该对象应该被分解。
回答by Chris Cudmore
I'm pretty shocked at some of the answers here.
我对这里的一些答案感到非常震惊。
In essence some people are saying "Don't test the private code, because that violates the TDD paradigm"
本质上,有些人在说“不要测试私有代码,因为这违反了 TDD 范式”
Test the damn code. Do whatever you need to in order to make sure that it works exactly as it should.
测试该死的代码。做任何你需要做的事情,以确保它完全按照它应该的方式工作。
Personally, I would make the methods protected or default, write the tests, run the tests, and upon success, revert back to private. At this point, I would comment out the relevant tests, and leave an instruction block above them:
就个人而言,我会将方法设置为保护或默认,编写测试,运行测试,并在成功后恢复为私有。此时,我会将相关测试注释掉,并在它们上方留下一个指令块:
/** Sorry about this, but I inherited a mess... * if you need to test these methods, expose them in source and un-comment the following * lines */
/** 对此很抱歉,但我继承了一个烂摊子... * 如果您需要测试这些方法,请在源代码中公开它们并取消注释以下 * 行 */
But absolutely never let rigid adherence to a development methodology get in the way of improving code.
但是绝对不要让严格遵守开发方法妨碍改进代码。
回答by Dror Helper
If you want to test Helpermethods you can change them from private but you might consider this.
如果您想测试Helper方法,您可以将它们从私有更改,但您可以考虑这样做。
You should not unit test private details of your implementation mainly because it might change due to refactoring and "break" your test.
你不应该对你的实现的私有细节进行单元测试,主要是因为它可能会由于重构和“破坏”你的测试而改变。
回答by Lorin
This is one of those cases where I would say go ahead and break the rules.
这是我会说继续违反规则的情况之一。
If you were designing the class from scratch, you definitely don't want helper methods to be unit tested on their own, but... since you are refactoring an existing class, it's acceptable to bend the rules in order to make sure you don't break anything.
如果您是从头开始设计类,您绝对不希望对辅助方法进行单独的单元测试,但是……由于您正在重构现有的类,因此可以改变规则以确保您不这样做不要破坏任何东西。
Making them protected will let you test the helpers themselves, to make sure they still have the behavior you are expecting as you pull the logic out of the big hairball method, as well as allow you to stub them out and return fixed responses so that you can make sure the big method you are refactoring behaves as expected for certain results of the helper methods.
使它们受到保护将让您自己测试助手,以确保在您从大毛球方法中提取逻辑时,它们仍然具有您期望的行为,并允许您将它们存根并返回固定响应,以便您可以确保您正在重构的大方法对于辅助方法的某些结果按预期运行。
But you're not done yet at that point. Splitting the method up isn't really getting to the root of your problem. Now that you have the method broken up and a set of (slightly unorthodox) tests that show you exactly what all of the logic does, you are in a good position to re-examine the whole class and try to figure out why the method was so big in the first place. Most likely your whole class also needs to be broken up into smaller units with discrete responsibilities that will then be easier to test without bending any rules.
但到那时你还没有完成。拆分方法并不能真正解决问题的根源。既然您已经分解了该方法并进行了一组(有点非正统的)测试来准确地向您展示所有逻辑的作用,那么您就可以重新检查整个类并尝试找出为什么该方法是一开始就这么大。很可能你的整个班级也需要分解成具有离散职责的更小的单元,这样在不违反任何规则的情况下更容易测试。
回答by Nick Veys
You unit test those helper methods by writing unit tests that exercise those portions of your code.
您可以通过编写单元测试来对这些辅助方法进行单元测试,以执行代码的这些部分。
You defined a public API in this class for a reason, right? Test that. If it works, the class works.
您出于某种原因在此类中定义了公共 API,对吗?测试一下。如果它有效,则该类有效。
Use code coverage tools to help you know whether a sufficient portion of that class is being tested, and if it's not, write more unit tests to exercise the public API and hit those corners that aren't being covered.
使用代码覆盖工具来帮助您了解该类是否有足够的部分被测试,如果没有,编写更多单元测试来练习公共 API 并找到那些没有被覆盖的角落。
回答by Dónal
You basically have 2 options:
你基本上有两个选择:
Increase the scope of the helper methods from private to default. You can then test these methods (assuming the test classes are in the same package as the test subject). This improves the testability of the class but you sacrifice some encapsulation
Leave everything the way it is. This will prevent you from writing very fine-grained tests, but doesn't require you to sacrifice any encapsulation.
将辅助方法的范围从私有增加到默认。然后您可以测试这些方法(假设测试类与测试对象在同一个包中)。这提高了类的可测试性,但你牺牲了一些封装
让一切保持原样。这将阻止您编写非常细粒度的测试,但不需要您牺牲任何封装。
Personally, I would choose (2), because you shouldn't really need to test private methods. The class should be tested through it's public interface (which in turn will call the private methods. Testing private methods can result in brittle tests, i.e. tests that fail when only the internal behavior of a class changes.
就个人而言,我会选择 (2),因为您不应该真的需要测试私有方法。该类应该通过它的公共接口进行测试(反过来会调用私有方法。测试私有方法可能会导致脆弱的测试,即只有当类的内部行为发生变化时测试才会失败。
There is a third option (which I'm reluctant to mention): use reflection (or some other voodoo) to invoke private methods within your test class. This has the disadvantages of (1) and also the disadvantages intrinsic to reflective code (e.g. bypasses type checking and is hard to read)
还有第三种选择(我不愿提及):使用反射(或其他一些巫术)在测试类中调用私有方法。这具有 (1) 的缺点以及反射代码固有的缺点(例如绕过类型检查并且难以阅读)
回答by Jay
As Don and Dror say, making the methods public so you can create unit tests for them breaks encapsulation. You then tie yourself to a particular implementation. By making them public, you declare to the world that these methods are part of the published interface and therefore their specifications are locked.
正如 Don 和 Dror 所说,将方法公开以便您可以为它们创建单元测试会破坏封装。然后,您将自己与特定的实现联系起来。通过将它们公开,您可以向全世界声明这些方法是已发布接口的一部分,因此它们的规范已被锁定。
Personally, I'd go for a more pragmatic solution: Keep them private and don't write unit tests. If you get to a case where a public method fails and you can't figure out why but you think it might be a problem in one of your private methods, then temporarily make them public, write the unit test, debug, and when you're done, make them private again and comment out the unit test.
就个人而言,我会寻求更实用的解决方案:将它们保密,不要编写单元测试。如果您遇到公共方法失败的情况并且您无法弄清楚原因,但您认为这可能是您的一个私有方法中的问题,那么暂时将它们设为公共,编写单元测试,调试,以及何时完成后,再次将它们设为私有并注释掉单元测试。

