Once you've used dependency injection to ensure you're only testing the code contained in your target object and don't test (again) the code from external dependencies, you can create and configure mock objects to replace a real object with a test double.
Test doubles are objects that behave exactly the same as other objects, but allow you to configure their methods to return any desired value (or simply return null), so you don't need to worry about their internal logic. You only need to define
by contract the public interface of the
double test object, the input method parameters, and their expected output results. You could even configure the behavior of the mock object to allow methods to call the original logic, while the rest of the methods return
null by default.