I watched the recording of the first #TDDLive webinar session yesterday. It was a really good conversation (nice to see a fishbowl format in action) and I’d recommend watching it if you get the chance. The part of the conversation about mocks was interesting as panellists were bringing up their experience of codebases (or people talking to them about codebases) that had loads of brittle tests because of their use of mocks. Due to this type of problem, the use of mocks has gained something of a reputation for being a bad technique and something to be avoided. In the session it was interesting to hear Nat Pryce talk about the origins of mocks in the context of creating state machines and wanting to confirm their outbound contracts. Personally, the main use I’ve made of mocks is as a placeholder for something I don’t want to create at this point in time so that I can reduce cognitive load, stay focused and concentrate on implementing the unit under test (or unit under design is probably more accurate). These are then like scaffolding that you can replace with the real implementation once you’ve got the mindshare and focus to move on. What interests me is that there must be a whole group of people out there who build test suites based on mocks, then realise that those test suites are brittle (in their context) and come up with the answer “mocks are bad”.
This took me back to the very early days of Enterprise JavaBeans when I was talking to someone about the different types of EJB and their remote interfaces. The person I was talking to was aghast about the idea of entity (data) EJBs having a remote interface because of the degree of chattiness this implied. I hadn’t really thought this through at the time (quite a common occurrence) as I thought that there must be a good reason for the remote entity interface to be there. However, stepping back and thinking about it, making remote calls from one layer of EJBs to another layer would obviously add a terrible overhead in terms of performance and complexity. I’m sure that it was useful in some scenarios but for most people it would be a poor design choice. However, in those early days of EJBs it would have been easy to just follow the docs unless you stepped back, looked at it and said “this can’t possibly be right”.
This came to mind yesterday because it feels like the people with those brittle codebases full of mocks should maybe have had a “this can’t possibly be right” moment. I suppose I’m in the privileged position of knowing a bunch of the people involved in coming up with mock objects so my initial reaction to them being a “bad thing” would be “this can’t possibly be right”. For me, this emphasises the importance of due diligence and going back to the source. If something doesn’t seem right then, to quote Gatiss and Moffatt’s Sherlock “do your research“. Rather than assuming that something is bad, go back to the original context for it being created and look at the writings of people closely connected with it (I’m sure there’s a book about this…). If your context is markedly different or the problem you’re trying to solve is dissimilar then why would you expect a tool or technique to give you good results. Any tool or technique is essentially a solution to a problem in a context (to coin a phrase) so try not to assume that it’s bad just based on your results or someone you saw on Twitter.
In many ways, this feels like just another variant on “select() isn’t broken”. If the thing isn’t working for you, put in the hard yards to make sure you’re using it as intended and putting in a good level of due diligence into the implementation (see also, TDD, pairing, mobbing, scrum, etc.)
Hi Andy,
do you have any book recommendation for testing without relying on heavy mocks? I have “Unit Testing” by Vladimir Khorikov and “the art of Unit Testing” by Roy Osherove on my reading list. I struggle most with the decision which larger “units” to choose when not mocking everything. When I test single classes as units it’s simple to mock “all” other dependencies but combining classes to larger units seems to take more compute cycles. Is there a text/guide/tip for this?
Best regards,
Tim
Hi Tim,
It’s a good question. The two books I used repeatedly as part of my TDD education were Kent Beck’s TDD by Example and the GOOS book (Growing Object-Oriented Software Guided by Tests). The rest of it was largely through in-person conference/meetup sessions and learning from people I worked with. Because I tend to work in a “London school” approach test-driving a system from the outside-in I’ve never really thought much about the granularity of units to aggregate together for a larger (integration) test as I have that test to start with because I’ve started more coarse-grained and then worked inwards. I’m struggling to think of an example of working the other way where I’ve had to make that sort of decision but I’ll post a reply if one springs to mind.
Regards
Andy
Hi Andy,
Thanks for you detailed reply. I’ll start my literature research then and take those into consideration too.
I have the suspicion that good testing skills are “tacit knowledge”, i.e. “knowledge that cannot be captured through words alone” as described by Cedric Chin on his blog (https://commoncog.com/blog/the-tacit-knowledge-series/). I’d like to also watch the webinar you refer too, but the sign-up process from cucumber’s website is broken (and they don’t answer to twitter messages to fix it…).
To that end I’m trying to find streams of developers doing live TDD on youtube. At least mpj has made something (https://www.youtube.com/watch?v=G2KV3YlvDFQ) even though I fear I need some example with the kind of heavy frameworks I have to to use in my current job.