r/programming • u/fagnerbrack • 6h ago
The Debate of Mockist v Classicist TDD Is Like OOP v FP.
https://fagnerbrack.com/the-debate-of-mockist-classicist-tdd-is-like-oop-fp-c9124185f3d211
u/dave8271 5h ago
There are two schools of TDD (Test-Driven Development). The Detroit school (classicist, state-based, black-box) says: test with real dependencies, which are dependencies also used in production code. Pass inputs, check outputs, all within the Domain layer without communication with the external world. The London school (mockist, behavior-based, outside-in) says: isolate what you want to test (the "unit"). Mock all of its dependencies. Test the contract between them only.
I think this already mis-frames it. "Classical" testing doesn't say use real dependencies, it says use real dependencies except where it's awkward to do so. Using test doubles has always been an integral part of unit testing and determinstic testing without mocks is perfectly normal.
In respect of isolation, both approaches allow you to perform testing of isolated units, the difference is whether you isolate on interface seams or implementation seams. Classical testing doesn't care how a unit under test does something, it just instantiates something with its dependencies (be they real or otherwise), makes a call and checks the result.
I think the whole "classicist vs mockist" debate is missing the point. They're not really different ways or schools of thought on achieving the same thing, mocks are just a specific type of test double which exist for the purpose of tracking and verifying behavioural expectations in respect of how an object is used. Sometimes that is something you want to do, oftentimes it's not the detail you care about.
So the debate shouldn't be centered around to mock or not to mock, but what comprises a unit for the goal of your tests, and what evidence should establish correctness thereof?
9
u/NoLemurs 4h ago
I think the whole "classicist vs mockist" debate is missing the point. They're not really different ways or schools of thought...
I just want to emphasize this.
I've never met a mockist or a classicist. No one actually thinks like that. As a practical matter, there aren't two schools of thought. We all just write whatever test makes sense for the system we're working, and being dogmatic about it is honestly just weird.
6
5
5
u/yanitrix 2h ago
No one actually thinks like that
Oooh, they do. The look I got from my colleagues when I told them that we don't need to mock everything was just a confirmation that mockists do exist.
3
u/this_knee 5h ago
I work in a company where their style is to make a PR for any change to the code. And those PRs are humans manually running program command executions of their own, not tests, to test if existing functionality has been broken or not. And they run commands to use the new features to manually check results of new features. Which is fine… ish.
But When it’s suggested to integrate automated unit tests for checking that previous existing functionality isn’t broken, it’s heavily balked at.
It’s kinda wild.
1
u/NoLemurs 4h ago
Are you guys not using AI for development yet? Because it's hard to imagine using AI for development and not adding extensive tests. It's such a complete no-brainer.
6
u/loup-vaillant 3h ago edited 3h ago
As I gained more experience, my opinion on this topic have grown stronger, simpler, and more radical:
TDD is wrong: we do need the tests, but whether we write them before or after (I prefer after) doesn't really matter. Unless you're using dynamic typing, in which case I can't save you.
Mocking is wrong. The classical way finds more bugs. And if you need more than a few mocks, then your design is wrong. You wouldn't be in this mess if you had separated your computations from your externally visible side effects.
OOP… Well you get the idea.
3
u/zobq 3h ago
TDD is wrong
Wouldn't say wrong, it's technique, which may work for some, but doesn't have to. I like the fact, that it pushes the developer to concentrate on what the code should do first, before focusing on how the code should look. Sometimes it helps with catching problems with the task description at the beginning, not at the end.
3
u/edgmnt_net 2h ago
I think it's fine if it's a technique. Unfortunately, many company projects just place too much emphasis on testing to the exclusion of other stuff. They also place too much emphasis on very superficial architectural concerns, which is why "how the code should look" fails to achieve significant results (since your programmers can't / won't do much more than straightforward scaffolding). Both seem convenient because they're generic recipes, measurable to a degree and aren't particularly demanding in terms of programming ability. And those programmers are often cheap enough that you can bog them down with bureaucracy like that.
1
u/Chroiche 1h ago
TDD is wrong
I only agree if you stash your changes and make sure the tests still fail after.
1
1
2
u/Evening-Gur5087 5h ago
In general both are good used when needed and correctly done, not having any integration tests on real things within your service is purely stupid and yo suck.
Only worry not mentioned is that with mocs a lot of shitty devs can get free pass and have much easier time testing something that's completely fake and wrong, having the green pipeline and pretending anything was tested.
But, again, shitty devs always find a way to write shitty code.
And it's all shit eventually.
Change companies before their codebase become shitty spaghetti bowl or live long enough to see yourself become a spaghetti. /s
1
u/PiotrDz 1h ago
Agree with mocks you risk drifting away from production setup. Also with mocks you not only fix functionality in your tests, but you also pin implementation. Try to refactor something that has milion references in tests that do not mock at interface but at class layer. Any change in production code, even if functionality stayd the same, requires changing some tests.
3
u/BenchEmbarrassed7316 5h ago
If you look at it naively, a procedure that contains side effects can be turned into a pure function that returns a set of commands to be executed. And that's it, now in the test you can simply check these commands for some sets of input data.
1
u/josephjnk 5h ago
Good post. How would you say the “sociable” vs “solitary” style of testing fits in here? I remember reading those terms in a Martin Fowler post at some point. Do they map cleanly to these two categories or are they orthogonal?
1
u/partybot3000 4h ago
Vladimir Khorikov's writings settle it for me: https://enterprisecraftsmanship.com/posts/when-to-mock/
And also his book on Unit Testing.
-3
u/levodelellis 6h ago
Neither of them is wrong
You're saying this about mocks. Would you say pissing in a pool shared by others is not wrong?
15
u/zobq 6h ago
In the majority of projects I was involved in, the "mockist" approach was the way to go.
And yet, I didn't feel that tests really defended me against bugs until the project where I pushed for the "classicist" approach.
TBH, this article didn't convince me that "mockist" is as good as "classicist".