Hacker News new | ask | show | jobs
by karlmdavis 1564 days ago
I’m really not clear what’s going on with the null implementations… aren’t those just very boring mocks?
4 comments

That’s my impression as well. Almost always when people advocate narrow tests without mocks they end up using something that’s not called a mock but ultimately isn’t distinguishable from a mock.

Which I don’t think necessarily invalidates the article (which I’ve only skimmed so far, but already strikes me as having a lot going for it), just some terminology used. It’s perfectly reasonable, regardless of terminology, to say: here are some techniques that encourage testability and high confidence in those tests. And it appears to me there’s a lot of that in the article. So with that said, I’m gonna go give it a more thorough read :)

I answered this question here: https://news.ycombinator.com/item?id=30591607
(Poster here)

Agreed. Perhaps what differentiate those from "normal" mocks is:

1) They only apply to "infrastructure" (so databases, external services etc). Basically the article says: "It's okay to use mocks sparingly, to avoid costly and flaky tests involving external services".

2) They are defined along with the production code, and _tested accordingly_. Which I assume means that you test the "null implementations"/"infrastructure mocks" by making sure they are always aligned with the real interactions. This avoids the danger of "normal mocks" to diverge from the real interactions.

What I would like to understand better, instead, is if there is a way to avoid all of this system to break once the infrastructure is two layers below the code you're testing. Because you can inject a null implementation into ApplicationClass, but what you have a UpperApplicationClass which depends on ApplicationClass? You either have to unravel the dependencies yourself to inject NullImplementation inside ApplicationClass inside UpperApplicationClass (which defies the point of the article, in a way), or you have to resort to a DI framework, which I personally abhor (I've still to find a single case in which it is a net benefit and not just a magic way of obfuscating the code).

> Which I assume means that you test the "null implementations"/"infrastructure mocks" by making sure they are always aligned with the real interactions. This avoids the danger of "normal mocks" to diverge from the real interactions.

When using a typed language (TS, Java, etc) this is also the case for mocks, isn't it? I don't see a reason why the implementation of the `createNull()` factory should be less prone to go out of sync with the implementation than mocks (as long as the type signatures are checked).

Same, it seems to me that the article is based on the idea that

    val app = new AppClass(new MockServer)
    assert(...)
is bad but

    val app = new AppClass(Server.createMock())
    assert(...)
is good. I for one see no difference.