Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Is using dependency injection (DI) essential for unit testing?

I can't think of another alternative for isolating code so it can be tested. Also, all the examples I have ever seen use this pattern. Is that because it is the only viable option or are there other alternatives?

share|improve this question
4  
Dependency Injection is not essential, but the broader concept of Inversion of Control is. –  Jeremy Heiler Mar 22 '12 at 15:56
    
There is something to be said for the scale here. If I have a small code base with very few layers then DI may not be useful. –  JB King Mar 22 '12 at 18:44
    
@JBKing if you have a small code base you don't need layers or unit testing –  Sklivvz Jan 31 at 20:43
add comment

7 Answers

up vote 25 down vote accepted

DI makes unit testing much easier. But you can still write unit tests without DI. Lots of unit tests have been written already before DI became widespread. (Of course, some of these used techniques identical or very similar to DI without knowing it has a fancy name :-)

I myself have used e.g. interfaces and factories a lot before learning about DI. The actual factory class name may have been read from a config file, or passed to the SUT as an argument.

Another approach is using singletons (or globally accessible data in general). Yes, I know it is not recommended by many (including myself) in general. Still it may be viable in specific situations, especially if the singleton contains static configuration data which is not test case specific, but differs between production and test environment. Of course it has its known problems, so DI is superior if you can use it. But often (e.g. in legacy systems) you can't.

Talking of which, Working Effectively With Legacy Code describes a lot of tricks to get legacy code covered by tests. Many of these are not nice, and aren't meant as a long term solution. But they allow you to create the first valuable unit tests to an otherwise untestable system... which enables you to start refactoring, and eventually (among others) introduce DI.

share|improve this answer
    
Agreed, DI is particularly usefull for mocking objects. But there are many scenarios where DI is useless in tests. –  Kemoda Mar 22 '12 at 15:42
    
@Kemoda like for example what? –  BЈовић Mar 22 '12 at 15:43
    
@VJovic For example standalone objects. I think of a method that takes some arguments and performs some stuff but does not depend on another component (thus no need for DI). –  Kemoda Mar 22 '12 at 15:52
    
@Kemoda It sounds like you're describing functional programming, and you are using DI. You're injecting your dependencies as method parameters. –  Erik Dietrich Mar 22 '12 at 16:05
2  
@huggie, why would implementation details get leaked here? The dependency injected is typically hidden behind an interface, and the whole point is that the client class has no idea of - and is not concerned with - whether the actual implementation of this dependency is a real production class or a mock. Its instantiation happens outside the client class, it only gets to see the ready-made instance. –  Péter Török Dec 28 '13 at 17:47
show 5 more comments

Yes, there are alternatives to the use of DI for isolation.

One alternative is to use factories or a ServiceLocator which can be configured from tests to return mock objects instead of real ones.

Another is to use a suitable isolation framework or mocking tool. Such tools exist for just about every modern programming language (for Java, C#, Ruby, and Python, at least). They can isolate a class being tested from the implementation of other classes/types, even when the tested class directly instantiates its dependencies.

share|improve this answer
add comment
  • Dependency injection is not essential for unit testing

  • Inversion of control on other hand is essential when you want to swap one implementation for another.

share|improve this answer
add comment

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.

share|improve this answer
add comment

No, DI is not essential for unit testing, but it helps a lot.

You can use factories or locators and test as you would with DI (just not as elegant and would require more setup).

Also, Mock Objects would be important in legacy systems where many calls are delegated to functions instead of dependencies. (Mock Objects can also be extensively utilized in a proper setup as well)

There, can of course, be setups where testing is nearly impossible. But this is not based on whether or not dependency injection is used.

share|improve this answer
add comment

Decoupling is essential for unit testing. DI is a great way to achieve decoupling.

share|improve this answer
1  
Excellent summary. –  Joachim Sauer May 4 '12 at 10:31
1  
A very true statement that in no way answers the question. –  Travis Apr 20 at 15:14
add comment

Depending on the technologies that you're using, you can isolate dependencies without using DI. For instance, in the .NET world, Moles allows you to isolate dependencies without the DI pattern.

That said, I believe these isolation frameworks are written and intended for situations in your code with external dependencies (filesystem, database, etc). That is, the fact that one can do this doesn't mean he or she should.

Dependency injection allows unit testing, but it also allow modification of an object's behavior without altering the code of that object (open/closed principle). So, it isn't just testable code, but flexible code that results. I've generally found that there is a heavy correlation between maintainable/flexible code and testable code.

share|improve this answer
3  
Or Moles lets you think you've got clean, well factored testable code because you are testing through magic. –  Wyatt Barnett Mar 22 '12 at 15:55
    
@WyattBarnett Yeah, very true. Moles has a wince-inducing ability to get someone to say "who needs all of this polymorphism and open/closed stuff, anyway?!?" –  Erik Dietrich Mar 22 '12 at 16:07
1  
Moles was replaced by fakes, and from the fakes page "The Fakes framework helps developers create, maintain, and inject dummy implementations in their unit tests" Sounds like DI to me. –  Sign Mar 22 '12 at 17:00
1  
@Sign Your link also says, "The Fakes framework can be used to shim any .NET method, including non-virtual and static methods in sealed types.". The fact that the isolation frameworks can be used in conjunction with DI doesn't mean that they are DI. –  Erik Dietrich Mar 22 '12 at 18:40
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.