Unit testing dilemma/question • r/angularjs
- Well, one issue we ran across is how can we properly test private functions.
- Some people were saying there really isn’t a way to test the private functions directly and that by testing the public functions calling those private functions, we were implicitly testing them.
- One other answer I found was to pull out the private functions into services/factories so they can be reused and tested properly.
- For example, most have a function that ultimately, across the controllers, accomplish the same task, but get there differently.
- Pulling our functions out into a single service would make that service HUGE in order to allow it to handle all possible save scenarios across the controllers.
Hello! My team and I were discussing different ways of bettering our unit tests and one topic that came up is, ‘Are we unit testing correctly?’…
@Beepop_Agency: Unit testing dilemma/question:
Suppose you start with a single public function and no private functions. Obviously, you would write tests for that public function and be done (since that’s all there is). Now say you refactor that public function, extracting a section of it into a private helper function. The test that you wrote for the public function should still work correctly, and the fact that the code has been partially delegated to a private function is just an implementation detail, not something that you need to write a test around.
Now if i instead start with with the public and private function in already in place, the result is the same: i can write my tests around the public function, and treat the private function as an implementation detail.
However, there are times when the public function combined with all the private functions it calls result in a very high cyclomatic complexity, and thus it would be much more convenient to write tests around the private function.
For those cases, i will typically expose the private method publicly. It’s not elegant, but it gets the job done. One convention for indicating that a method should be considered private is to prefix it with an underscore. If everyone’s onboard that could work, but i prefer to be more explicit than that, and do something like this:
If you’re writing code inside this service, then you can directly reference myPrivateFunction. But if you’re writing code from the outside, then you have to type myService._private.myPrivateFunction(), so there’s no chance of overlooking that the function is meant to be private.
One downside to this approach is that if you try to create a mock for myService._private.myPrivateFunction, that mock will only change what’s exposed to the outside world, it will not change the function internally, so myPublicFunction will continue to call the real implementation of myPrivateFunction. So if you need to mock a private function, then you’d need to rewrite the code in myPublicFunction to call service._private.myPrivateFunction(), instead of calling myPrivateFunction() directly.
Again though, i usually just write my tests around the public functions, and reserve this exposing strategy for particularly complicated cases.