I have a controller that handles various cronjobs and I wanted to write unit tests for each function in the controller. The controller (lets call it TasksController) extends a base controller (let’s call it BaseController). Previously, I was creating new objects of individual Task classes inside each concerned function, but since that’s bad practice (ref1 ref2)that makes one’s code hard to test, I used DI container to inject dependencies instead. A sample function from Task Controller would look like:
<?php
namespace OrgControllers;
use DIContainer;
use OrgDbConnection;
use OrgLogger;
use OrgTasksSampleTask;
class TasksController extends BaseController
{
public $container;
// Task Objects:
public $sampleTaskObject;
public function __construct(Container $container)
{
parent::__construct($container);
$this->container = $container;
// All objects for the task classes go below:
$this->sampleTaskObject = $container->get(SampleTask::class);
}
function runSampleTaskObjectRun($request, $response, $args)
{
$this->sampleTaskObject->run();
return $response->withStatus(200);
}
}
The constructor for the base controller looks like:
class BaseController
{
public $container;
public $dbConn;
public $logger;
function __construct(Container $container)
{
$this->container = $container;
$this->dbConn = $container->get(DbConnection::class);
$this->logger = $container->get(Logger::class);
}
}
In my unit tests, I am able to run tests by directly doing:
$this->container = $this->createMock(Container::class);
$this->tasksController = new TasksController($this->container);
$sampleTaskMockObject = $this->createMock(SampleTask::class);
$this->taskController->sampleTaskObject = $sampleTaskMockObject
However, I would like to use my DI container to inject this mock dependency to my controller instead (ideally without changing the control flow of my controller). I have looked at a few references online that mock dependencies, but couldn’t find one that does use container in a similar way.