is
now ready for review, and works as expected. That could make this
discussion unnecessary.
Il giorno gio 29 ago 2019 alle ore 14:46 Aryeh Gregor <ayg(a)aryeh.name> ha
scritto:
On Thu, Aug 29, 2019 at 1:02 AM Krinkle
<krinklemail(a)gmail.com> wrote:
What did you want to assert in this test?
In a proper unit test, I want to completely replace all non-value
classes with mocks, so that they don't call the actual class' code.
This way I can test the class under test without making assumptions
about other classes' behavior.
This is not possible at all if any method is declared final. As soon
as the class under test calls a final method, you cannot mock the
object. This is without any use of expects() or with() -- even just
method()->willReturn().
I find there is sometimes a tendency for a test
to needlessly duplicate
the
source code by being too strict on expecting
exactly which method is
called
to the point that it becomes nothing but a more
verbose version of the
source code; always requiring a change to both.
Personally, I prefer a style of testing where it providers a simpler view
of the code. More like a manual of how it should be used, and what
observable outcome it should produce.
The idea of good unit tests is to allow refactoring without having to
worry too much that you're accidentally changing observable behavior
in an undesired way. Ideally, then, any observable behavior should be
tested. Changes in source code that don't affect observable behavior
will never necessitate a change to a test, as long as the test doesn't
cheat with TestingAccessWrapper or such.
This includes tests for corner cases where the original behavior was
never considered or intended. This is obviously less important to test
than basic functionality, but in practice, callers often accidentally
depend on all sorts of incidental implementation details. Thus
ideally, they should be tested. If the test needs to be updated, that
means that some caller somewhere might break, and that should be taken
into consideration.
On Thu, Aug 29, 2019 at 1:12 AM Aaron Schulz <aschulz4587(a)gmail.com>
wrote:
Interfaces will not work well for protected
methods that need
to be overriden and called by an abstract base class.
If you have an interface that the class implements, then it's possible
to mock the interface instead of the class, and the final method
problem goes away. Of course, your "final" is then not very useful if
someone implements the interface instead of extending the class, but
that shouldn't happen if your base class has a lot of code that
subclasses need.
On Thu, Aug 29, 2019 at 10:37 AM Daniel Kinzler <dkinzler(a)wikimedia.org>
wrote:
Narrow interfaces help with that. If we had for
instance a cache
interface that
defined just the get() and set() methods, and
that's all the code needs,
then we
can just provide a mock for that interface, and
we wouldn't have to
worry about
WANObjectCache or its final methods at all.
Any interface would solve the problem, even if it was just a copy of
all the public methods of WANObjectCache. That would be inelegant, but
another possible solution if we want to keep using final.
_______________________________________________
Wikitech-l mailing list
Wikitech-l(a)lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/wikitech-l