“TDD it’s so easy” that’s what they tell us. There’s not trick to it, it’s just a simple trick. This article shows one way to unit test Silex controllers.
The way to implement TDD on a Silex controller is composition, low coupling and dependency injection. At its most basic a Silex controller has no relationship to Silex. However its easy to end up with controllers tightly coupled to the Application and Request classes.
One issue is the DI container getting injected in to the controller directly. This is ok when the routes are small and controllers are closures but when they are separate classes it gets a little out of control.
Another issue is using the controller resolver. This forces methods to take a specific form and have specific parameters. It can also force the methods to always use the Request.
These two things lead to the controller having dependencies on the Application and Request classes which in turn makes the controller’s dependencies harder to mock and the controller harder to test.
With a simple trick or two 😜 those dependencies can be removed and the controller made more straight forward to test.
The first trick is to create the controller as a service and call it from within the route. This way dependencies can be handled by the DI container.
The second trick is to not pass in the entire request but only the values that the method requires. These values could be variables from the route, the POST, the GET etcetera.
Putting this all together gives the following contrived example controller:
Which in turn has its own unit test:
Then the controller and the application are tied together in the web index:
The controller has no dependencies on the Request or Application classes. This means the unit test doesn’t need to mock those classes. Other dependencies are passed in the constructor. Then in index.php the controller is created as a service and has a value from the application container inserted in to it. The routes then do a bit of lifting to hide the Application and Request classes from the controller.