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 unittested.
Example (using DI) This implementation depends on Employee, Account, ....
bool hasPermissionToTranferMony(Employee employee, Account from, Account to, Money amount)
{
if (amount > 100 && imployee.isStudent())
return false;
if (to.getOwner().getFamiliyName() == Employee.getFamiliyName() && ...
return false; // cannot transfer money to himself;
...
}
After seperation of data-gethering and calculation
bool hasPermissionToTranferMony(Employee employee, Account from, Account to, Money amount)
{
return hasPermissionToTranferMony(employee.isStudent(), Employee.getFamiliyName(), to.getOwner().getFamiliyName(), ....);
}
// the actualal permission calculation
static bool hasPermissionToTranferMony(boolean isStudent, string employeeFamiliyName, string receiverFamiliyName, .....)
if (amount > 100 && isStudent)
return false;
if (receiverFamiliyName == employeeFamiliyName && ...
return false; // cannot transfer money to himself;
...
}
The calculation part can be easily tested without dependency injection.