Паттерны, DI и UnitTesting

panoptik

Новичок
Приветствую уважаемое сообщество

Занялся тестированием одного проекта. И столкнулся с задачкой моккирования объекта, который шлет курл запросы. Но архитектура этого не очень позволяет.
В лучшем случае я добился того что явно объявляю мок-класс с тем же именем и в результате использую именно свой класс вместо того который должен вызываться автолоадом

теперь приведу примерную картину кода который нужно протестировать. и собственно вопрос как лучше его протестировать или отрефакторить, чтобы его стало возможно тестировать

// базовый класс интерфейс
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();
задача стоит протестировать модульными тестами классы MyServiceN

нужно моккировать класс CurlRequest - который создается в конструкторе PrimitiveService и тем самым избежать отправки непосредственных запросов при тестах

в связи с этим у меня есть следующие мысли вопросы:
1. используется ли здесь какой либо паттерн проектирования и как он называется? подозреваю что это что-то типа фабрики
2. я думаю что здесь можно (или даже нужно) впилить DI (Dependency Injection) и в конструкторе к сервису передавать каким реквестером (объект типа CurlRequest) будет пользоваться сервис
3. ну и хотелось бы услышать советы как такое дело тестируется на самом деле и что я делаю не так
 
Сверху