Testable Controllers with dependencies

Viewed 3029

How can I resolve dependencies to a controller that is testable?

How it works: A URI is routed to a Controller, a Controller may have dependencies to perform a certain task.

<?php

require 'vendor/autoload.php';

/*
 * Registry
 * Singleton
 * Tight coupling
 * Testable?
 */

$request = new Example\Http\Request();

Example\Dependency\Registry::getInstance()->set('request', $request);

$controller = new Example\Controller\RegistryController();

$controller->indexAction();

/*
 * Service Locator
 *
 * Testable? Hard!
 *
 */

$request = new Example\Http\Request();

$serviceLocator = new Example\Dependency\ServiceLocator();

$serviceLocator->set('request', $request);

$controller = new Example\Controller\ServiceLocatorController($serviceLocator);

$controller->indexAction();

/*
 * Poor Man
 *
 * Testable? Yes!
 * Pain in the ass to create with many dependencies, and how do we know specifically what dependencies a controller needs
 * during creation?
 * A solution is the Factory, but you would still need to manually add every dependencies a specific controller needs
 * etc.
 *
 */

$request = new Example\Http\Request();

$controller = new Example\Controller\PoorManController($request);

$controller->indexAction();

This is my interpretation of the design pattern examples

Registry:

  • Singleton
  • Tight coupling
  • Testable? No

Service Locator

  • Testable? Hard/No (?)

Poor Man Di

  • Testable
  • Hard to maintain with many dependencies

Registry

<?php
namespace Example\Dependency;

class Registry
{
    protected $items;

    public static function getInstance()
    {
        static $instance = null;
        if (null === $instance) {
            $instance = new static();
        }

        return $instance;
    }

    public function set($name, $item)
    {
        $this->items[$name] = $item;
    }

    public function get($name)
    {
        return $this->items[$name];
    }
} 

Service Locator

<?php
namespace Example\Dependency;

class ServiceLocator
{
    protected $items;

    public function set($name, $item)
    {
        $this->items[$name] = $item;
    }

    public function get($name)
    {
        return $this->items[$name];
    }
} 

How can I resolve dependencies to a controller that is testable?

3 Answers
Related