Правильный способ тестирования методов, которые могут возвращать исключения

0

Я тестирую метод User::validateAdmin() который может выполнять три функции:

  • Если действительный администратор, верните true
  • Если истек срок действия admin, верните false
  • Если не объявление, бросьте NotAnAdminException

Пока у меня это:

$result = $this->User->validateAdmin($validAdmin);
$espected = true;
$this->assertEquals($result, $espected);

$result = $this->User->validateAdmin($disabledAdmin);
$espected = false;
$this->assertEquals($result, $espected);

$this->setExpectedException('NotAnAdminException');
$result = $this->User->validateAdmin($anotherUserRole);
$espected = null;
$this->assertEquals($result, $espected);
$this->setExpectedException(null);

... но это заставляет PHPUnit игнорировать все последующие использования NotAnAdminException, ожидаемые или нет.

Что правильно правильно проверить мои три сценария?

  • 0
    Похоже, вы поставили все это в одном тесте?
  • 1
    stackoverflow.com/questions/14561908/… ?
Показать ещё 5 комментариев
Теги:
cakephp
cakephp-2.0
phpunit

2 ответа

0
Лучший ответ

Поскольку PHPUnit не продолжает проверку после ожидания исключения, подход, показанный в вопросе, является ошибочным, потому что PHPUnit обертывает тест в регулярном блоке try/catch, поэтому, как только генерируется исключение, остальные утверждения в тесте метод игнорируются. Кроме того, метод \PHPUnit_Framework_TestCase::setExpectedException работает так, как ожидалось: тест проходит тогда и только тогда, когда \PHPUnit_Framework_TestCase::setExpectedException данное исключение.

Самый чистый подход состоял бы в разделении утверждений различными способами:

public function testvalidateAdminValid(){
    $validAdmin = ........;
    $result = $this->User->validateAdmin($validAdmin);
    $espected = true;
    $this->assertEquals($result, $espected);
}

public function testvalidateAdminExpired(){
    $disabledAdmin = ........;
    $result = $this->User->validateAdmin($disabledAdmin);
    $espected = false;
    $this->assertEquals($result, $espected);
}

public function testvalidateAdminNotAnAdmin(){
    $anotherUserRole = ........;
    $this->setExpectedException('NotAnAdminException');
    $this->User->validateAdmin($anotherUserRole);
}

Если вы предпочитаете придерживаться всех связанных тестов в одном и том же методе, вы должны сами эмулировать setExpectedException, например:

try{
    $result = $this->User->validateAdmin($anotherUserRole);
    $this->fail('Failed to throw NotAnAdminException');
}catch(NotAnAdminException $e){
    $this->assertEmpty($result);
}
  • 1
    Или просто используйте стиль аннотации блочного документа @expectedException .
2

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

Я также рекомендую вам писать тесты в стиле BDD. Поэтому вы должны проверить ожидаемое поведение, например:

public function shouldReturnTrueForAdmin() {
    //given
    $validAdmin = ........;

    //when
    $result = $this->User->validateAdmin($validAdmin);

    //then
    $this->assertTrue($result);
}

Тестирование исключений в этом стиле затруднено в PhpUnit.

Вы можете попробовать CatchException от узо лакомства:

public function shouldFailIfNotAdmin() {
    //given
    $anotherUserRole = ........;

    //when
    CatchException::when($this->User)>validateAdmin($anotherUserRole);

    //then
    CatchException::assertThat()->isInstanceOf("NotAnAdminException");
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню