With that out of the way, I would recommend using a test double in exactly one kind of situation: When it's genuinely awkward to use the real thing. Concrete examples include talking to a third-party API, testing for error conditions that are difficult or impossible to reliably organically produce, and when the real dependency hasn't actually been implemented yet.
As for the different kinds of test doubles, Fowler has a concise overview at https://martinfowler.com/bliki/TestDouble.html that is just about the clearest explanation I've seen of the different kinds and what they're used for.