mastodon.online is one of the many independent Mastodon servers you can use to participate in the fediverse.
A newer server operated by the Mastodon gGmbH non-profit

Server stats:

11K
active users

Testing Without Mocks: A 🧵.

So a few days ago I released this massive update to my article, "Testing Without Mocks: A Pattern Language." It's 40 pages long if you print it. (Which you absolutely should. I have a fantastic print stylesheet.) I promised a thread explaining what it's all about.

This is the thread. If you're not interested in TDD or programmer tests, you might want to mute me for a bit.

Here's the article I'm talking about: jamesshore.com/v2/projects/tes

www.jamesshore.comJames Shore: Testing Without Mocks: A Pattern Language

@jamesshore To aid in my own understanding, I tried to fit this into my own schema of testing approaches, and figure out the major decisions this approach makes. This might be useful feedback, or it might just be repeating the original idea in my own (less coherent) words. Or I might just have misunderstood it all. Let's find out!

@jamesshore Question #1: where do you switch away from using production (whether that be code, data, infrastructure, or something else)? Or, to put it another way, what do we fake? The typical case with mocks is to fake the immediate dependencies with mocks. In the opposite case where we run the full system, it's the config that's fake: the stack of code is completely real but we (for instance) change a config file to point the system at a different database (again, running for real).

@jamesshore Nullables says that we should run as much of our own code as possible, but avoid using real infrastructure. So, we fake out those dependencies on infrastructure at the lowest level e.g. faking out `stdout.write()`.

@jamesshore One possible advantage: if you're mocking immediate dependencies, then you end up mocking an awful lot of your interfaces at one point or another. Faking out dependencies at the lowest level might well mean a much smaller, and therefore more manageable, set of interfaces that you have to fake.

@jamesshore Question #2: how do we make the fakes? Rather using a mocking framework, or making the real thing with different config, we create embedded stubs. One way to think about them is as in-memory implementations of the interface. For instance, instead of writing to stdout, we just stash the value in a field. Instead of checking what was written to stdout, we check the stashed value. Instead of reading from stdin, we get the value to return from a field.

James Shore

@zwobble Not exactly right. They’re stubs, not fakes, which means they don’t try to provide an in-memory implementation. Instead, they just return pre-configured values, no matter what is written. It’s technically possible to write a fake, rather than a stub, but stubs are much easier and have been sufficient in my experience. With one exception: my Clock infrastructure wrapper uses a fake, not a stub.

@zwobble Also, the output tracking is unrelated to the stubs, and works the same regardless of whether you’re using a Nulled instance or a normal one.

@jamesshore To check I've understood: "works the same" in that you can always create an output tracker using the exact same mechanism, both in production and tests, even if you don't actually do so in practice in production?

One of the other nice things about colocating code in that way is that it makes it more natural to add those sorts of affordances that make testing easier.

@zwobble Yes. You call e.g., `log.trackOutput()` and you get the same results back regardless of whether it’s Nulled or not. There’s an extensive example of how it works for both JavaScript and Java in the article.

@zwobble (under “Output Tracking”)

@jamesshore Ah, possibly a difference in terminology -- when I say "fake", I mean that in a very broad sense -- anything that could be used in place of the production implementation, even if not a complete implementation and it's (for instance) just using canned responses. So, I'd consider stubs to be a subset of fakes. (Happy to be told my terminology is weird and inconsistent with everyone else, or that I have in fact just misunderstood!)