If we had infinite resources, we wouldn't bother stubbing methods out. Stubbing adds a layer of complexity to our tests.
However, our machines have limited computing power. Tests that touch multiple objects (even in the background), or read and write files, or perform complex calcuations take longer to run than tests that touch a single object/method.
When tests take too long to run, developers stop running tests.
Tests are no good to us if we don't run them.
We have to make tests run quickly for them to maintain their value.
In order to make our tests run quickly, we try to test things (especially expensive things) only when we need to, and only once.
So, if we have a complex calculation, we want to test it directly once to make sure it works. If that test fails, we know our calculation is broken.
However, if we have multiple other objects that use the output of that complex calculation, and we test those other objects, and they call the complex calculation, then that slows our tests unnecessarily.
We don't need to test that calculation indirectly if we've tested it directly.
You can substitute File/IO (including querying our database) for the complex calculation above. These are also things we try to avoid when possible.
Because of this we prefer unit tests to integration tests.
A unit test is not truly a unit test if it reaches out to collaborators (e.g. our complex calculation); that's an integration test.
Stubs provide a way for us to test methods without testing/calling their collaborators. This help keep our unit tests fast.
Instead of performing that complicated calculation (which is tested elsewhere), just assume that it's working and that it sends me back what I expect. Then test that when the method I'm trying to test (the system under test
) receives the result, it does what we want it to do.
This leads to an interesting corollary: if the collaborating method that you're calling isn't slow, maybe you don't bother stubbing it out. This is where there seems to be more disagreement in the community based on how dogmatic people are about isolating their unit tests.
More resources below if you'd like to dig further into the arguments/tools of how to write good, efficient tests.
Sometimes the question of how much to mock/stub is framed as a difference between classicist and mockist schools of testing, which some of the links below address.
I'm not as familiar, but believe that the majority of this has root in Extreme Programming. Many of the concepts there should feel familiar based on Turing's approach.
- 467 tests, 0 failures, 0 confidence: Katrina Owen on testing.
- Magic Tricks of Testing: Resource material for some of the articles below.
- Rules for Good Testing
- Writing Tests Like Sandi Metz: What to test.
- Test Confidence: More on what to test.