panoptik
Новичок
Приветствую уважаемое сообщество
Занялся тестированием одного проекта. И столкнулся с задачкой моккирования объекта, который шлет курл запросы. Но архитектура этого не очень позволяет.
В лучшем случае я добился того что явно объявляю мок-класс с тем же именем и в результате использую именно свой класс вместо того который должен вызываться автолоадом
теперь приведу примерную картину кода который нужно протестировать. и собственно вопрос как лучше его протестировать или отрефакторить, чтобы его стало возможно тестировать
// базовый класс интерфейс
// наследуемый класс интерфейс
потомок и его реализация
в нормальном коде я просто вызываю
задача стоит протестировать модульными тестами классы MyServiceN
нужно моккировать класс CurlRequest - который создается в конструкторе PrimitiveService и тем самым избежать отправки непосредственных запросов при тестах
в связи с этим у меня есть следующие мысли вопросы:
1. используется ли здесь какой либо паттерн проектирования и как он называется? подозреваю что это что-то типа фабрики
2. я думаю что здесь можно (или даже нужно) впилить DI (Dependency Injection) и в конструкторе к сервису передавать каким реквестером (объект типа CurlRequest) будет пользоваться сервис
3. ну и хотелось бы услышать советы как такое дело тестируется на самом деле и что я делаю не так
Занялся тестированием одного проекта. И столкнулся с задачкой моккирования объекта, который шлет курл запросы. Но архитектура этого не очень позволяет.
В лучшем случае я добился того что явно объявляю мок-класс с тем же именем и в результате использую именно свой класс вместо того который должен вызываться автолоадом
теперь приведу примерную картину кода который нужно протестировать. и собственно вопрос как лучше его протестировать или отрефакторить, чтобы его стало возможно тестировать
// базовый класс интерфейс
PHP:
abstract class PrimitiveService
{
/**
* @var CurlRequest
*/
protected $curl;
protected $settings;
/**
* @var string
*/
protected $cookieFile;
public function __construct($settings)
{
$this->settings = $settings;
$this->init();
}
public function init() {
$this->cookieFile = Config::getParam('tmpPath') . DIRECTORY_SEPARATOR .
get_class($this) . '_' . md5($this->settings['login']) . '.cookie';
$this->curl = new CurlRequest(array(
'url' => $this->settings['url'],
'cookieFile' => $this->cookieFile,
));
if(!$this->checkLogin()) {
throw new Exception(get_class($this) . ': Cannot login to service');
}
}
abstract protected function checkLogin();
}
PHP:
abstact class BaseService extends PrimitiveService
{
abstact public function f1();
abstact public function f2();
abstact public function f3();
public static function getService($serviceName)
{
// получаю параметры сервисов из конфига
$config = Config::getParams('services');
switch($serviceName) {
case 'service1':
return new MyService1($config[$serviceName]);
case 'service2':
return new MyService2($config[$serviceName]);
case 'service3':
return new MyService3($config[$serviceName]);
default: throw new Exception('Trying to connect unknown service ' . $serviceName);
}
}
}
PHP:
class MyService1 extends BaseService
{
public function f1()
{
// implementation here
}
public function f2()
{
// implementation here
}
public function f3()
{
// implementation here
}
protected function checkLogin()
{
// implementation here
}
}
в нормальном коде я просто вызываю
PHP:
$serviceName = 'service1'; // get from request
$service = BaseService::getService($serviceName);
$service->f1(); // вызов методов интерфейсов
$service->f2();
нужно моккировать класс CurlRequest - который создается в конструкторе PrimitiveService и тем самым избежать отправки непосредственных запросов при тестах
в связи с этим у меня есть следующие мысли вопросы:
1. используется ли здесь какой либо паттерн проектирования и как он называется? подозреваю что это что-то типа фабрики
2. я думаю что здесь можно (или даже нужно) впилить DI (Dependency Injection) и в конструкторе к сервису передавать каким реквестером (объект типа CurlRequest) будет пользоваться сервис
3. ну и хотелось бы услышать советы как такое дело тестируется на самом деле и что я делаю не так