If you have an unit test on private members, then you can't change the implementation safely without breaking tests.
The point of the unit test is to test the interface in isolation, not the implementation - e.g. do you really expect when testing a hash-map the elements to be in specific order, or do you test for their presence?
> If you have an unit test on private members, then you can't change the implementation safely without breaking tests.
This makes absolutely no sense
You change the private implementation, you change the unit test. It's that simple
Then you keep your API the same so that external users don't break.
It seems to be from the same people that like to whine about "missing tests and lack of coverage" quite funnily. It seems they like to nitpick and idolize tests instead of shipping
Depends. If we take the example of a library, then there are some tests which should never break ( except if the major version increases). But it is entirely sensible to check if you broke something internally during development.
I've been a game developer for 15+ years (mainly C++), never used unit tests, just good old plain asserts, sometimes ad-hoc code that creates/simulates errors or slowdowns. Pretty much QA people testing your game/tools and some form of automated tests (run this level, expect this to happen). Then I changed jobs, started writing in Java (+ GoogleWebKit and Javascript), was exposed to Unit, integration and end-to-end testing. Do I know it properly? Hell no. I'm still confused.
But this is what I seems to be getting out of it: You are given a black box, with inputs and outputs. There is also a spec (it could be in your head for all I know) that defines that for certain inputs, certain outpus are expected. This spec also tries to cover quite a lot distinct cases. Each such representative case of input and output is an unit test. (If your spec was really in your head, your unit tests kind of becomes it, or I like to think about it in this way - a Unit Spec :)).
The tricky part is when this blackbox is internally working with other blackboxes. Unit testing is all about testing the blackbox in isolation from other blackboxes. As such one needs to isolate them away. Currently what I'm using is DI (Dependency Injection) with guice/gin/dagger to achieve that.
Thanks for all comments, it seems I have to fill my gaps in what I know.
This is true for totally isolated unit tests but false for tests that require stubbing. You can theoretically use the same tests for a map implemented with one version of a hash table or the other. But once you start testing classes with dependencies, your tests inevitably touch implementation details. For example, unit testing a hash map that is backed by a memcached server would require some form of stubbing.
The metatesting reason for this confusion is that in the example you used, the scope of unit testing is the same as the scope of integration testing. If a class has 0 dependencies, a unit test is also an integration test, because it tests all the dependencies of the class, of which there are none.
So going back to your original point, your affirmation is true for full integration tests, i.e. tests that do not stub any dependency. If you do not stub your network connection to the memcached server, the same test - albeit with a different setup - can be used for a local hash table implementation.
The method should still do the same thing, regardless if it is private or public. If you purposefully create a new method and get rid of the old one, regardless if this is done by creating and deleting or by modifying, then the unit test should be changed as well.
In short, you are testing the interface of that private method, not the implementation.
The point of the unit test is to test the interface in isolation, not the implementation - e.g. do you really expect when testing a hash-map the elements to be in specific order, or do you test for their presence?