No, dependency injection is not essential for unit testing.
Dependency injection helps if you have a class that needs a dependent class-instance to do some sub-processing. Instead of DI you can seperate the logic of a business-method into a data-gethering-part (that is not unit-testable) and a calculation part that can be unit-tested.
Example (using DI) This implementation depends on Employee, Account, ...
bool hasPermissionToTransferMoney(Employee employee, Account from, Account to, Money amount)
{
if (amount > 100 && employee.isStudent())
return false;
if (to.getOwner().getFamiliyName() == employee.getFamilyName() && ...
return false; // cannot transfer money to himself;
...
}
After seperation of data-gathering and calculation:
bool hasPermissionToTransferMoney(Employee employee, Account from, Account to, Money amount)
{
return hasPermissionToTransferMoney(employee.isStudent(), employee.getFamilyName(), to.getOwner().getFamilyName(), ...);
}
// the actual permission calculation
static bool hasPermissionToTransferMoney(boolean isStudent, string employeeFamilyName, string receiverFamilyName, ...)
if (amount > 100 && isStudent)
return false;
if (receiverFamilyName == employeeFamiliyName && ...
return false; // cannot transfer money to himself
...
}
The calculation part can be easily tested without dependency injection.