A case for NOT using Dependency Injection <gasp!>

4/5/2022

NOT use Dependency Injection???

Stay with me here. Dependency Injection has certainly gained tremendous support, and is without question extremely useful. However...on my current project we've seen some benefits of not using it, and I wanted to take some time to share why. And this is no small project! After all, no project is the same, and no tool is best for all circumstances.

TL;DR

On our project we've elected to write fully data-driven, full stack Integration Tests and almost no Unit Tests that require mocking or injection. Essentially the full stack gets executed with each integration test (all the way to DB writes). As a result each integration test was quick to write, and covered a lot of code.

The Long Answer

Sometimes it's difficult to get upper management buy in on automated testing (both integration and unit tests). The approach we've implemented is to test everything from (mostly) the Controller level: Filling in View Models (or in the case of WebAPI, DTOs) and making calls to Controller methods. The tests end up performing full round-trip integration to the DB and back (sometimes even through a WebAPI middle layer).

The Advantages

The following are some benefits of doing all full-round-trip integration tests:

  • A lot of code gets tested with each integration test. Any failure along the way will get identified.
  • We don't have to pass interfaces everywhere. This was especially helpful in our case when we would find ourselves coding some low-level DB code that would sometimes benefit from calling data-methods from other modules. We wouldn't have to go fully up the chain and pass that DI item down the chain. We simply called that other module. This really simplified our complex middle-layer code.
  • Not using interfaces for everything helps navigate the code. Simply click on a method, hit F-12, go to the implementation, find another function inside it you need to go to...F-12 again. Navigating on interfaces isn't that simple.
  • No Mocking and Stubbing. None. Code we never had to write. For our Test Projects, we simply add the project references, and started calling Controller Methods in our tests.

What we were missing out on

Obviously there are advantages to DI in general. But for our project, we didn't have a sufficient need for all those. Ultimately all of our code simply needed to read/write to the DB.

One of the biggest benefits of DI is the ability to isolate the code-under-test. If you have some complex logic in a method you want to focus a test on, it's beneficial to not worry about DB connections, network issues. Plus you can Mock exactly what you want sub-calls to do. But in our case, we simply re-ran tests that had any system/network failures. We just didn't have a lot of need for DI.

Disadvantages

There are obviously trade-offs. Here's what I would list as our disadvantages:

  • LOTS of data in the DB. Obviously we were generated a lot of data since each call created data. We ended up either have to write good clean-up code, or deal with ever-growing data.
  • Test run-times. Since each was a full-round-trip, tests that could have run quicker were longer. At one point we had our automated regression tests running every 2 hours. Eventually these had to be run only twice a day. But with scheduled automated test, we would simply check them when they finished.
  • False-negatives any time a dependency failed. This could be from a DB connection issue, network issue, or some other dependency failure. Until these were resolved, tests remain indeterminant.

Conclusion

Sometime old-school integration tests have their advantages. In our case, it saved us a lot of time.


Please register or login to add a comment.

Comments (displaying 1 - 1):
No comments yet! Be the first...


  • C#/.NET
  • T-SQL
  • HTML/CSS
  • JavaScript/jQuery
  • .NET 8
  • ASP.NET/MVC
  • Xamarin/MAUI
  • WPF
  • Windows 11
  • SQL Server 20xx
  • Android
  • XBox
  • Arduino
  • Skiing
  • Rock Climbing
  • White water kayaking
  • Road Biking