Let’s say I want to test a simple helper that takes a class name as an argument and makes a redirection.
How am I supposed to test this if the function is called in many places from inside a couple of controllers? Should I test every class name that was passed as a parameter in the whole code (write them in the provider function myself)? Or is there a magical function which does that for me?
Your question is the exact reason why dependency injection — when done correctly (not how most popular frameworks “implement” it) — is touted as the ultimate in code testability.
To understand why, lets look at how “helper functions” and class-oriented programming make your controllers difficult to test.
The entire point of unit testing is to verify that “units” of code work in isolation. If you can’t isolate functionality, your tests are meaningless because their results could be tainted by the behavior of the other code involved. This can result in what statisticians call Type I and Type II errors: basically, this means you can get test results that might be lying to you.
In the code above, the helper cannot be easily mocked to determine that
MyController::doSomethingworks in complete isolation from outside influences. Why not? Because we can’t “mock” the behavior of the helper method to guarantee ourdoSomethingmethod actually adds 100 to the helper result. We’re stuck with the helper’s exact behavior (returning 42). This is a problem that correct object-orientation and inversion of control eliminate entirely. Let’s consider an example of how:If
MyControllerasks for it’s dependencies instead of using the static helper function , it becomes trivial to mock the outside influences. Consider:Now, it’s trivially simple to test that
MyController::doSomethingdoes in fact add 100 to whatever it gets back from the answer machine:This example also demonstrates how the correct use of interfaces in your code can greatly simplify the testing process. Test frameworks like PHPUnit make it very easy to mock interface definitions to perform exactly what you want them to in order to test the isolated functionality of code units.
So I hope these very simple examples demonstrate how powerful dependency injection is when it comes to testing your code. But more importantly, I hope they demonstrate why you should be wary if your framework of choice is using static (just another name for global), singletons, and helper functions.