Unit test helper methods?

2019-03-15 02:17发布

I have classes which previously had massive methods so I subdivided the work of this method into 'helper' methods.

These helper methods are declared private to 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?

Also in order to test these using a mock object I would need to change their visibility from private to protected, is this desirable?

9条回答
老娘就宠你
2楼-- · 2019-03-15 02:53

One way is to omit private and put the tests in the same package. Then the tests can call the internal methods but no one else (= outside the package) can.

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.

查看更多
可以哭但决不认输i
3楼-- · 2019-03-15 02:53

If you want to test Helper methods you can change them from private but you might consider this.

You should not unit test private details of your implementation mainly because it might change due to refactoring and "break" your test.

查看更多
姐就是有狂的资本
4楼-- · 2019-03-15 02:54

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.

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.

查看更多
家丑人穷心不美
5楼-- · 2019-03-15 02:56

You basically have 2 options:

  1. 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

  2. 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.

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)

查看更多
成全新的幸福
6楼-- · 2019-03-15 02:57

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.

查看更多
兄弟一词,经得起流年.
7楼-- · 2019-03-15 02:58

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"

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.

查看更多
登录 后发表回答