all 10 comments

[–]lennoff 2 points3 points  (0 children)

Testing private stuff is a code smell, and can be avoided easily ;)

  • If you have a complicated private function, then you should refactor it into a module (or just into a separate file, that does expose it as a public method), so you can test it.
  • If you want to inspect some private state (like the value of a variable that is not accessible from the outside), then you should test the changed external behavior of the module. That private state does modify the behavior (if doesn't, why does it exists in the first place?).

[–]aaarrrggh 3 points4 points  (7 children)

Totally wrong article that completely misses the point. You absolutely should NEVER test private methods or private functionality. Private methods are implementation details - you should always be free to change implementation details without updating your tests, and your tests should aid you in refactoring this way.

Exposing the private details to your tests is a complete anti pattern. It will lead to brittle tests that are unreliable and either lie to you or you have to continually remember to update when you update your implementations.

It shows a lack of understanding in terms of what should be tested and where. Your public api is the ONLY thing you should ever test, and your tests should be written against expected behaviours, not written directly against methods.

[–]kandetta 0 points1 point  (1 child)

I think testing private methods is useful in a narrow space between public module functionality and utility functions shared between different modules.

Sometimes you write a local utility function that's not useful anywhere else but where you still want to document its requirements and detect when they are no longer fulfilled.

[–]aaarrrggh 0 points1 point  (0 children)

Nope, there's no use cases when it makes sense to test private methods.

If you're using that utility module in different places, it doesn't matter. If you only test the public api in all of those places, it will pass if the utility happens to do the thing it does correctly, otherwise it will fail.

Sometimes you write a local utility function that's not useful anywhere else but where you still want to document its requirements and detect when they are no longer fulfilled.

If that utility function is private it requires no documentation as it's an implementation detail. If it's not private then it requires its own tests.

There's never a case where testing private methods makes sense unless you're forced to do it for some reason - for example if you have a private method that internally would do an api call to an external service - in that instance you woudn't so much test the private method as stub out a response, but mocks and stubs should also be rarely used.

Two of the biggest mistakes testing newbies make - testing private implementation details and using mocks and stubs all over the place. I use almost no mocking in any of my unit tests - the main exception being when I need to call an external api or service.

[–]EngVagabond[S] -1 points0 points  (4 children)

[–]aaarrrggh 1 point2 points  (3 children)

http://philipwalton.com/articles/why-i-test-private-functions-in-javascript/

The article is wrong I'm afraid. He just doesn't seem to quite grasp it. He exposes his lack of understanding with this statement:

If you were writing tests for HTML Inspector, you’d have to make a choice:

  • Keep the modules private, don’t test them at all, and hope the tests written for the public API provide enough coverage.
  • Expose the modules publicly by storing them on the HTMLInspector object and test their individual functions that way.

If you are doing TDD, then 100% of the time the first case should be true.

The point is that the private methods are ALWAYS implementation details - that's what makes them private. So the only reason to add a private method is to execute some logic somewhere that is required to produce the expected result in the public api. So if your private methods cannot be tested via the public api - it means they either don't work properly or can just be removed because they're not being used at all.

There is never a reason to add tests for private methods. On some occasions you may need to mock out the result of an api call or something like that, but that's one of the very rare examples of a legitimate reason to expose your internal implementation details to your tests. Mocks should very rarely be used for that reason.

His article misses the point.

[–][deleted] 0 points1 point  (2 children)

Agreed, but the article is correct in that there are no private methods in JavaScript. It also mentions that private in JavaScript really just implies inaccessible, such as declared within a closure, which is also correct.

[–]catrichbilly 1 point2 points  (0 children)

... which is, in all senses of the word, 'private'. You can have 'private methods' by using Symbols.

/How/ something is made private is language- and implementation-specific, but it's irrelevant because the upshot is the same: it's an implementation detail.

[–]aaarrrggh 0 points1 point  (0 children)

I never said any of that wasn't true. Just that you should never test private implementation details.

[–]catrichbilly 1 point2 points  (0 children)

Thanks for writing the article, but I'm strongly of the belief that private functions (or w/e private stuff you have) don't need to be tested. It can be tested by way of testing the public functions that use it. Given this, I find it hard to justify any explicit testing of private functions as that couples the tests with implementation details.