Я пытаюсь успокоиться Модульное тестирование и мне нужно найти еще один кусок головоломки.
Я пытаюсь написать тесты для следующего кода. В этом случае у меня есть действительно простой Front Controller (написанный на PHP).
class frontController
{
public function routeRequest($oRequest)
{
$sClassname = $oRequest->getController();
$sMethod = $oRequest->getAction();
$oController = new $sClassname();
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
}
У меня проблема в том, что код создает новые объекты . Я легко могу макетировать объект запроса, чтобы я мог жестко контролировать то, что он будет фактически делать в моем тестовом примере. Я не уверен, что лучший способ на самом деле заменить контроллер на двойной тест.
В этой статье IBM предлагается использовать фабричный метод для создания моего контроллера, а затем переопределить его с помощью специфического класса, используемого для тестирования:
class frontController
{
public function routeRequest($oRequest)
{
$sMethod = $oRequest->getAction();
$oController = $this->createController($oRequest);
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
protected function createController($oRequest)
{
$sClassname = $oRequest->getController();
return new $sClassname();
}
}
и затем для тестирования возможно что-то вроде этого:
class testFrontController extends frontController
{
public function setMockController($oMockController)
{
$this->oMc = $oMockController;
}
protected function createController($oRequest)
{
return $this->oMockController;
}
}
(обратите внимание, что это не совсем то, о чем говорится в статье, но я думаю, что было бы очень полезно для меня, если бы это было сделано)
Другим решением может быть другой класс, который создает контроллер. Тогда это будет зависимый класс frontController. Таким образом, я могу заменить класс фабрики / создания во время тестирования на двойной тест. Примерно так:
class frontController
{
public function routeRequest($oRequest, $oControllerFactory)
{
$sMethod = $oRequest->getAction();
$oController = $oControllerFactory->create($oRequest);
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
}
class controllerFactory
{
public function create($oRequest)
{
$sClassname = $oRequest->getController();
return new $sClassname();
}
}
Полагаю, что об внедрении зависимостей можно было бы позаботиться в конструкторе фронт-контроллера или через установщик вместо параметра фактического метода "route".
Мне кажется, я предпочитаю вариант 2.
Является ли любой из этих двух методов правильным способом проверки такого рода вещей?
(возможно, здесь лучше сказать "хороший путь"!)
Любые мысли или предложения по варианту 1 против варианта 2 приветствуются или вообще любые альтернативы. Помните - главное в том, как протестировать объект, который сам создает другие объекты как часть его выполнения.
Спасибо!