CakePHP3: фиктивные методы в интеграционных тестах? - PullRequest
0 голосов
/ 02 октября 2018

Я новичок в модульном / интеграционном тестировании и хочу провести интеграционное тестирование моего контроллера, которое выглядит упрощенно так:

// ItemsController.php
public function edit() {

    // some edited item
    $itemEntity

    // some keywords
    $keywordEntities = [keyword1, keyword2, ...]

    // save item entity
    if (!$this->Items->save($itemEntity)) {
        // do some error handling
    }

    // add/replace item's keywords 
    if (!$this->Items->Keywords->replaceLinks($itemEntity, $keywordEntities)) {
       // do some error handling
    }
}

У меня есть модели Предметы и Ключевые слова , где Items принадлежит ToMany Keywords.Я хочу проверить ошибки обработки частей контроллера.Поэтому я должен смоделировать методы save () и replaceLinks () , чтобы они возвращали false.

Мой интеграционный тест выглядит следующим образом:

// ItemsControllerTest.php
public function testEdit() {

    // mock save method
    $model = $this->getMockForModel('Items', ['save']);
    $model->expects($this->any())->method('save')->will($this->returnValue(false));

    // call the edit method of the controller and do some assertions...

}

Это нормально работает для метода save ().Но это не работает для метода replaceLinks ().Очевидно, потому что это не часть модели.

Я также пробовал что-то вроде этого:

$method = $this->getMockBuilder(BelongsToMany::class)
    ->setConstructorArgs([
        'Keywords', [
            'foreignKey' => 'item_id',
            'targetForeignKey' => 'keyword_id',
            'joinTable' => 'items_keywords'
        ]
    ])
    ->setMethods(['replaceLinks'])
    ->getMock();

$method->expects($this->any())->method('replaceLinks')->will($this->returnValue(false));

Но это тоже не работает.Любые советы для насмешки метода replaceLinks () ?

1 Ответ

0 голосов
/ 02 октября 2018

При выполнении тестов контроллеров я обычно стараюсь имитировать как можно меньше, лично, если я хочу протестировать обработку ошибок в контроллерах, я пытаюсь вызвать фактические ошибки, например, предоставляя данные, которые не соответствуют правилам приложения / проверки.Если это приемлемый вариант, возможно, вы захотите попробовать.

При этом насмешливый метод ассоциации должен работать так, как показано в вашем примере, но вам также необходимо заменитьфактический объект ассоциации с вашей имитацией, потому что, в отличие от моделей, ассоциации не имеют глобального реестра, в который можно было бы поместить макеты (это то, что getMockForModel() сделает для вас), так что код вашего приложения будет использовать их без дальнейшего вмешательства.

Что-то вроде этого должно сделать это:

$KeywordsAssociationMock = $this
    ->getMockBuilder(BelongsToMany::class) /* ... */;

$associations = $this
    ->getTableLocator()
    ->get('Items')
    ->associations();

$associations->add('Keywords', $KeywordsAssociationMock);

Это изменит объект таблицы Items в реестре таблиц и заменит ее (add() коллекции ассоциации действует больше как установщик, т.е.он перезаписывает) свою фактическую Keywords связь с высмеянным.Если вы используете это вместе с имитацией Items, то вы должны убедиться, что макет Items был создан заранее, иначе таблица, полученная в приведенном выше примере, не была бы имитированной!

...