In general, we should not be unit testing private members regardless of the programming language.
If we find ourselves needing to access a private member during a unit test, it is likely because the private member is pointing to something we want to mock. In that case, we should be injecting it on object creation so that it can easily be substituted when testing (consider the db parameter from the sample code in this article, for example).
As a side note, if we find ourselves doing a lot of mocking and dependency injection during unit testing, it is likely because we have not properly segregated our integration logic from our business logic. But that could be the subject of a whole other article.
I've been using the Ice Factory pattern for years and even taught it to hundreds students so I quite like it (at least in ES5).
However, I've taken the example of testing but there is other ones. Suppose that there's an object Foo with an internal state bar which is a variable scoped to the constructor. For some reason, you don't want to expose bar to the world, yet you want to have a Foo.hasSameState(otherFoo) method. Since you can't access the private member, you're kinda screwed.
In short, I don't really recommend to create private members using this pattern or if you do you need to be really careful because you might very easily end up refactoring code.
If I understand correctly, what you're getting at is that – unlike some other languages – JavaScript doesn't yet support the notion of semi-private members (e.g. "protected" in Java or "friend" in C++). So, using a private member when what we really need is a semi-private member, will get us into trouble.
In general, we should not be unit testing private members regardless of the programming language.
If we find ourselves needing to access a private member during a unit test, it is likely because the private member is pointing to something we want to mock. In that case, we should be injecting it on object creation so that it can easily be substituted when testing (consider the
db
parameter from the sample code in this article, for example).As a side note, if we find ourselves doing a lot of mocking and dependency injection during unit testing, it is likely because we have not properly segregated our integration logic from our business logic. But that could be the subject of a whole other article.
I've been using the Ice Factory pattern for years and even taught it to hundreds students so I quite like it (at least in ES5).
However, I've taken the example of testing but there is other ones. Suppose that there's an object
Foo
with an internal statebar
which is a variable scoped to the constructor. For some reason, you don't want to exposebar
to the world, yet you want to have aFoo.hasSameState(otherFoo)
method. Since you can't access the private member, you're kinda screwed.In short, I don't really recommend to create private members using this pattern or if you do you need to be really careful because you might very easily end up refactoring code.
Thanks for the clarification.
If I understand correctly, what you're getting at is that – unlike some other languages – JavaScript doesn't yet support the notion of semi-private members (e.g. "protected" in Java or "friend" in C++). So, using a private member when what we really need is a semi-private member, will get us into trouble.
I definitely agree with that.
Yes exactly :)