Dependencies imply coupling. Often, the best way to remove coupling is to remove dependencies, or remove dependent logic from integrational flows.
The correct strategy is very situational, but in general, more reliance on pure functions and less reliance on mutation is a good start.
Another great strategy is to isolate program logic from I/O and side-effects.
Work back through this thread to see what I mean in the context of a pipeline of asynchronous functions. We start with some explicit logic and response handling in the pipeline flow and extract it from the pipeline by moving the responsibility into the promise context.
In other words, we let promises and promise composition handle the error branching and passing values to the next promise.
That eliminates the logic we would have needed to unit test and makes those tests redundant with the unit tests that browsers build to ensure promises behave as advertised.
That means we can write fewer tests without sacrificing any functionality or coverage, and our code is easier to read and maintain, too!
With no logic remaining to unit test, the pipeline only needs integration tests, and none of its own unit tests.
Since we no longer have any dependent logic, there is no need to mock dependencies anymore.