Могу ли я сделать фиктивное завершение redirect () в контроллерах, используя CakePHP 1.3 & Simpletest? - PullRequest
0 голосов
/ 14 февраля 2012

Я следую указаниям Марка Стори " Тестирование контроллеров CakePHP - издание Mock Objects " для проверки некоторых действий контроллера, имеющих перенаправления.В настоящее время я макет метода redirect () в простом тесте.Я хотел реорганизовать некоторый код, чтобы он выглядел следующим образом:

if (!$this->Model->someGuardCondition($id)){
  $this->redirect($this->referer());
}

if ($this->Model->save($this->data)){
  $this->redirect(array('controller' => 'controllerName', 'action' => 'actionName', $id));
}

Проблема в том, что если первое условие истинно, то я не хочу, чтобы тест когда-либо выполнял второе условие, так как это будет работатьв производстве.Есть ли способ заставить тест завершаться всякий раз, когда вызывается redirect (), не убивая весь набор тестов?Я знаю, что мог бы ставить оператор return после каждого перенаправления, но я бы не стал изменять код, чтобы тесты работали правильно.Должен ли я просто использовать кучу уродливых вложенных операторов if / else?

РЕДАКТИРОВАТЬ 20120215 Я постараюсь сделать мой пример кода более полным, чтобы продемонстрировать проблему:

some_controller.php:

class SomeController extends AppController
  function some_action($id) {
    if (!$this->Model->hasAuthorityToDoThis($id)){
      $this->Session->setFlash(__('The id is invalid for some reason'));
      $this->redirect($this->referer());
    }

   if ($this->Model->save($this->data)){
      $this->Session->setFlash(__('Save successful'));
      $this->redirect(array('controller' => 'controllerName', 'action' => 'actionName', $id));
   }
  }
}

some_controller_test.php:

class SomeControllerTestCase extends AppCakeTestCase {
  function testSomeAction() {
    $this->SomeController->Session = new MockSessionComponent();
    $this->SomeController->Session->expectOnce('setFlash');
    $this->SomeController->some_action('some-invalid-id');  // Note this is an invalid ID.

  }
}

Итак, как вы видите выше, я тестирую действие с неверным идентификатором.Это означает, что первое условие пройдет.Он установит флэш-сообщение как «Идентификатор недействителен по какой-то причине» и перенаправит к рефереру.В CakePHP редирект выйдет из скрипта при вызове редиректа, поэтому код никогда не попадет в модель-> save ().Однако, если я проверяю redirect () в тесте, метод, по сути, просто возвращается без эффекта, и контроллер продолжает работать после точки, которую он должен.Это хорошо тем, что он не прерывает набор тестов, но это плохо, потому что он фактически не отражает поведение реального кода.

Скажите, что вызов для сохранения $ this-> data - это хорошо.Тогда и первое и второе условия пройдут.Это приведет к сбою теста, потому что у вас должно быть установлено флэш-сообщение только один раз.

Я предполагаю, что нет способа легко написать подобный код, и было бы лучше просто придерживаться вложенного, если / elseблоки.Я просто пытался уменьшить цикломатическую сложность.

Ответы [ 2 ]

0 голосов
/ 31 января 2013

Просто используйте return:

$this->redirect($this->referer());
return;

Таким образом, действие вашего контроллера закончится после перенаправления, и это будет намного менее навязчивым изменением кода по сравнению со сложным if/else и т. Д.

0 голосов
/ 15 февраля 2012

Вложите ваши тесты:

while (!$complete) {
   if (!$this->Model->someGuardCondition($id)){
      $this->redirect($this->referer());
      $complete = 1;
      continue;
   }

   if ($this->Model->save($this->data)){
      $this->redirect(array('controller' => 'controllerName', 'action' => 'actionName', $id));
      $complete = 1;
      continue;
   }
}

Или вы можете использовать операторы if else:

if (!$this->Model->someGuardCondition($id)){
  $this->redirect($this->referer());
} elseif($this->Model->save($this->data)){
  $this->redirect(array('controller' => 'controllerName', 'action' => 'actionName', $id));
} else {
  return;
}

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

...