2015-09-22 11 views
0

У меня есть приложение, которое построено поверх другого фреймворка. У упомянутой структуры есть несколько объектов ценности, которые мне нужно расширить различными способами с использованием шаблона декоратора. Позволяет вызвать базовый объект Entity и классы декоратора Wrappers. У объектов одного и того же класса могут быть разные «типы», и для каждого из этих типов требуется различный класс Wrapper для раскрытия функциональных возможностей, относящихся к этому типу. Это приложение не является окончательным слоем и не контролирует, какие типы существуют или какие классы использовать для них (выполняется выше по цепочке), поэтому назначение должно быть динамическим.Unit Testing Dynamic Factory Class

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

<?php 

class WrapperFactory 
{ 
    protected $default_wrapper = null; 
    protected $typed_wrappers = []; 

    public function __construct($default){ 
     $this->setDefaultWrapper($default); 
    } 

    public function setDefaultWrapper($class){ 
     if ($this->validateWrapperClass($class)){ 
      $default_wrapper = $class; 
     } 
    } 

    public function getDefaultWrapper(){ 
     return $this->$default_wrapper; 
    } 

    public function setWrapperForType($class, $type){ 
     if($this->validateWrapperClass($class)){ 
      $this->$typed_wrappers[$type] = $class; 
     } 
    } 

    public function hasWrapperForType($type){ 
     return array_key_exists($type, $this->typed_wrappers); 
    } 

    public function getWrapperForType($type){ 
     if($this->hasWrapperForType($type)){ 
      return $this->typed_wrappers[$type]; 
     } 
     else{ 
      return $this->getDefaultWrapper(); 
     } 
    } 

    public function wrap($entity) 
    { 
     $class = $this->getWrapperForType($entity->type); 
     return new $class($entity); 
    } 

    protected function validateWrapperClass($class){ 
     if(class_exists($class) && class_implements($class, WrapperInterface::class)){ 
      return true; 
     }else{ 
      throw new BadMethodCallException("Wrapper must implement ". WrapperInterface::class . "."); 
     } 
    } 
} 

Я не совсем уверен, как правильно провести тестирование этого класса. Есть ли способ, которым я могу высмеять класс , который реализует интерфейс, а не объект? как я могу проверить, что класс, назначенный типу, работает правильно? Должен ли я явно объявлять фиктивный класс или два в моих тестовых файлах или есть способ их издеваться?

ответ

0

Если вы создаете объект Mock, PHPUnit создаст класс, который расширяет класс, в котором вы создали mock. Поскольку это также работает с интерфейсами, вы можете просто создать макет своего интерфейса и получить его название класса:

$mock = $this->getMock('WrapperInterface'); 
$class = get_class($mock); 
$this->assertTrue($factory->validateWrapperClass($class)); 
+0

Отлично, это работает отлично! –