| A mock is a fake. Just so we are using the same terminology I'll define my terms: Fake: a test implementation of something that stands in for production code to solve certain testing problems. A fake can implement an API and provide simplified behaviour. A good example might be a piece of code that stands in for a hardware device driver that you use when you don't have access to the hardware. Another very common use of a fake is to fake out a UI layer. There are lots of other common places for pure fakes. There are 2 special kinds of fakes: - Stub: An implementation that returns canned data. - Mock: An implementation that encapsulates an expectation. The most common type of mock is a mock that encapsulates the expectation that a certain function is called. Sometimes you don't want to write a pure fake because it's more than you need. Most of the time you can adequately test what you want without talking directly to some inconvenient real API with a stub. There are many good reasons to use pure fakes or stubs. Like I mentioned, it might be because hardware is involved. Sometimes it's because you are using some SaaS that you don't want to really access in your tests. Very often it's because the real service is just too slow (I'll need another post to describe why this is super important, but even if you don't agree I hope you will see that it's not the only reason to use a fake or a stub). As soon as you use a fake or a stub, though, you leave a hole in your tests -- you have no way of knowing that the production code uses the real service in the production code. This is when you need a mock. You can go without testing it, but mocking it in this circumstance is almost always a better solution. Of course, there is a school of thought that reaches for mocks first. This school of thought is often referred to as the "London School" because it is very popular (and probably originated from) several very famous people who work in London. The GOOSE book, which describes outside-in programming is probably the best description of this school of thought. I've met quite a few of the people who are standard bearers for this school of thought and they are very talented developers. Again, I would need another post to describe why I don't think it's the best technique to reach for first, but it's an area where reasonable people can disagree. Outside-in and promiscuous mocking has several advantages -- especially when you are less experienced. It provides a framework for reasoning about how to do design. Personally, I am not a big fan in general, but there are times I use it -- I just replace the mocks with non-faked tests after the fact. So, while I agree that one should have the mindset to use mocks as a technique of last resort, it's still a valuable tool in your arsenal. |
I find that any additional couplings to your code makes the couplings you do have more painful to work with.
Some people think that by adding this kind of 'tight coupling' - low level mocks / unit tests - you feel that pain earlier on in the design process and that pain drives you to make a better, more loosely coupled code design.
Personally, I think that this approach is rather like forcing kids to smoke cigarettes every day to show them how much of a filthy dirty habit it is.