2016-02-03 6 views
4

Я подозреваю, что «лучший» ответ на мой вопрос - использовать инъекцию зависимостей и полностью исключить проблему. К сожалению, у меня нет такого варианта ...Как превентивно издеваться над классом, который получает экземпляр другим классом

Мне нужно написать тест для класса, который создает экземпляр библиотеки сторонних разработчиков. Я хочу обмануть/заглушить класс библиотеки, чтобы он не вызывал вызовы API в реальном времени.

Я использую phpunit в каркасе CakePHP v3.x. Я могу издеваться над библиотекой и создавать ответы на заглушку, но это не мешает «реальному» классу создавать экземпляр кода вне моего теста. Я считал, что пытаюсь высмеять класс (ы) вверх по потоку от экземпляра, но есть лот из них, что сделало бы тест невероятно громоздким для написания/поддержки.

Есть ли способ каким-то образом «заглушить» экземпляр класса? Аналогично тому, как мы можем сказать, что модуль php ожидает вызова API и задает возвращаемые данные?

+0

Вы заявляете, что вы не можете вводить зависимости, но можете ли вы заменить «новый» оператор для вызова Factory? Таким образом, вы можете взять контроль над Фабрикой и заставить ir вернуть макет. – gontrollez

ответ

0

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

Вот пример из phpunit.de сайта (глава 9):

public function testObserversAreUpdated() 
{ 
    // Create a mock for the Observer class, 
    // only mock the update() method. 
    $observer = $this->getMockBuilder('Observer') 
        ->setMethods(array('update')) 
        ->getMock(); 

    // Set up the expectation for the update() method 
    // to be called only once and with the string 'something' 
    // as its parameter. 
    $observer->expects($this->once()) 
      ->method('update') 
      ->with($this->equalTo('something')); 

    // Create a Subject object and attach the mocked 
    // Observer object to it. 
    $subject = new Subject('My subject'); 
    $subject->attach($observer); 

    // Call the doSomething() method on the $subject object 
    // which we expect to call the mocked Observer object's 
    // update() method with the string 'something'. 
    $subject->doSomething(); 
} 

Если API возвращает что-то вы можете добавить волю() на второе утверждение следующим образом:

->will($this->returnValue(TRUE)); 
+0

Класс, о котором идет речь, намного дальше вверх по течению, чем только 1 уровень. Таким образом, даже если бы это сработало, это было бы похоже на 15 из этих типов вещей. Если я не ошибаюсь здесь. –

+1

Есть ли способ создать псевдоним класса, чтобы все, что создает экземпляр реального класса, будет актуальным, создайте ваш макет? –

+0

Если вы используете «-> will ($ this-> returnValue ($ someVariable))», то вы в основном ожидаете, что update() вернет $ someVariable. Однако сама update() не будет вызвана. Таким образом, вам не нужно будет проходить 1-й уровень. – timhysniu

0

Я сомневаюсь, что вы можете издеваться над созданием экземпляра, потому что «новый» - это языковая конструкция, и нет возможности издеваться над собственной функциональностью. Есть несколько вариантов, чтобы рассмотреть, один стоит, чем другие:

  • макет третьего партия API
  • завернуть библиотеку с собственным прокси/декоратор
  • издеваться вся библиотека и заменить его в композиторе для тестирования
Смежные вопросы