Кто-нибудь знает, существует ли assert
или что-то подобное, которое может проверить, было ли выброшено исключение в тестируемом коде?
Кто-нибудь знает, существует ли assert
или что-то подобное, которое может проверить, было ли выброшено исключение в тестируемом коде?
Ответы:
<?php
require_once 'PHPUnit/Framework.php';
class ExceptionTest extends PHPUnit_Framework_TestCase
{
public function testException()
{
$this->expectException(InvalidArgumentException::class);
// or for PHPUnit < 5.2
// $this->setExpectedException(InvalidArgumentException::class);
//...and then add your test code that generates the exception
exampleMethod($anInvalidArgument);
}
}
waitException () PHPUnit документация
Статья автора PHPUnit содержит подробное объяснение лучших практик тестирования исключений.
$this->setExpectedException('\My\Name\Space\MyCustomException');
setExpectedException
метод устарел, заменен на метод expectException
. :)
expectException()
. Хотя это могло быть очевидным для некоторых, для меня это было ошибкой .
Вы также можете использовать аннотацию docblock до выхода PHPUnit 9:
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
Для PHP 5.5+ (особенно с кодом пространства имен) я сейчас предпочитаю использовать ::class
IncorrectPasswordException
должно быть достаточно - что сообщение равно "Wrong password for bob@me.com"
является вспомогательным. Добавьте к этому то, что вы хотите потратить как можно меньше времени на написание тестов, и вы начинаете понимать, насколько важными становятся простые тесты.
Если вы работаете на PHP 5.5+, вы можете использовать ::class
разрешение для получения имени класса с помощью expectException
/setExpectedException
. Это обеспечивает несколько преимуществ:
string
так, это будет работать с любой версией PHPUnit.Пример:
namespace \My\Cool\Package;
class AuthTest extends \PHPUnit_Framework_TestCase
{
public function testLoginFailsForWrongPassword()
{
$this->expectException(WrongPasswordException::class);
Auth::login('Bob', 'wrong');
}
}
PHP компилирует
WrongPasswordException::class
в
"\My\Cool\Package\WrongPasswordException"
без PHPUnit быть мудрее.
Примечание : PHPUnit 5.2 введен
expectException
в качестве замены дляsetExpectedException
.
Код ниже будет проверять сообщение об исключении и код исключения.
Важно: он потерпит неудачу, если ожидаемое исключение не будет выдано.
try{
$test->methodWhichWillThrowException();//if this method not throw exception it must be fail too.
$this->fail("Expected exception 1162011 not thrown");
}catch(MySpecificException $e){ //Not catching a generic Exception or the fail function is also catched
$this->assertEquals(1162011, $e->getCode());
$this->assertEquals("Exception Message", $e->getMessage());
}
$this->fail()
я не думаю, что это будет использоваться таким образом, я не думаю, по крайней мере, в настоящее время (PHPUnit 3.6.11); это само по себе исключение. Используя ваш пример, если $this->fail("Expected exception not thrown")
вызывается, то catch
блок запускается и $e->getMessage()
является «Ожидаемое исключение не брошенную» .
fail
вероятно, принадлежит после блока catch, а не внутри try.
fail
не должен быть в try
блоке. Это само по себе вызывает catch
блок, выдающий ложные результаты.
catch(Exception $e)
. Этот метод работает очень хорошо для меня, когда я пытаюсь поймать определенные исключения:try { throw new MySpecificException; $this->fail('MySpecificException not thrown'); } catch(MySpecificException $e){}
Вы можете использовать расширение assertException, чтобы утверждать более одного исключения во время одного выполнения теста.
Вставьте метод в ваш TestCase и используйте:
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}
Я также сделал черту для любителей хорошего кода ..
assertException
не определено. Я также не могу найти его в руководстве по PHPUnit.
asertException
Метод не является частью оригинального PHPUnit. Вы должны унаследовать PHPUnit_Framework_TestCase
класс и вручную добавить метод, связанный в посте выше . Ваши тестовые примеры будут наследовать этот унаследованный класс.
Альтернативный способ может быть следующим:
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');
Пожалуйста, убедитесь, что ваш тестовый класс расширяется \PHPUnit_Framework_TestCase
.
Метод PHPUnit expectException
очень неудобен, потому что он позволяет тестировать только одно исключение на метод тестирования.
Я сделал эту вспомогательную функцию, чтобы утверждать, что какая-то функция выдает исключение:
/**
* Asserts that the given callback throws the given exception.
*
* @param string $expectClass The name of the expected exception class
* @param callable $callback A callback which should throw the exception
*/
protected function assertException(string $expectClass, callable $callback)
{
try {
$callback();
} catch (\Throwable $exception) {
$this->assertInstanceOf($expectClass, $exception, 'An invalid exception was thrown');
return;
}
$this->fail('No exception was thrown');
}
Добавьте его в свой тестовый класс и назовите так:
public function testSomething() {
$this->assertException(\PDOException::class, function() {
new \PDO('bad:param');
});
$this->assertException(\PDOException::class, function() {
new \PDO('foo:bar');
});
}
Текущие " лучшие практики " PHPUnit для тестирования исключений кажутся .. тусклыми ( документы ).
Так как я хотел больше, чем текущая expectException
реализация, я использовал эту черту в своих тестовых примерах. Это всего ~ 50 строк кода .
assert
синтаксисassertNotThrows
Throwable
ошибки PHP 7Я опубликовал эту AssertThrows
черту для Github и packagist, чтобы ее можно было установить с помощью composer.
Просто чтобы проиллюстрировать дух синтаксиса:
<?php
// Using simple callback
$this->assertThrows(MyException::class, [$obj, 'doSomethingBad']);
// Using anonymous function
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
Довольно аккуратно?
Пожалуйста, смотрите ниже для более полного примера использования:
<?php
declare(strict_types=1);
use Jchook\AssertThrows\AssertThrows;
use PHPUnit\Framework\TestCase;
// These are just for illustration
use MyNamespace\MyException;
use MyNamespace\MyObject;
final class MyTest extends TestCase
{
use AssertThrows; // <--- adds the assertThrows method
public function testMyObject()
{
$obj = new MyObject();
// Test a basic exception is thrown
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
// Test custom aspects of a custom extension class
$this->assertThrows(MyException::class,
function() use ($obj) {
$obj->doSomethingBad();
},
function($exception) {
$this->assertEquals('Expected value', $exception->getCustomThing());
$this->assertEquals(123, $exception->getCode());
}
);
// Test that a specific exception is NOT thrown
$this->assertNotThrows(MyException::class, function() use ($obj) {
$obj->doSomethingGood();
});
}
}
?>
public function testException() {
try {
$this->methodThatThrowsException();
$this->fail("Expected Exception has not been raised.");
} catch (Exception $ex) {
$this->assertEquals($ex->getMessage(), "Exception message");
}
}
assertEquals()
IS assertEquals(mixed $expected, mixed $actual...)
, реверс , как в вашем примере, поэтому он должен быть$this->assertEquals("Exception message", $ex->getMessage());
Вот все утверждения об исключениях, которые вы можете сделать. Обратите внимание, что все они являются необязательными .
class ExceptionTest extends PHPUnit_Framework_TestCase
{
public function testException()
{
// make your exception assertions
$this->expectException(InvalidArgumentException::class);
// if you use namespaces:
// $this->expectException('\Namespace\MyException');
$this->expectExceptionMessage('message');
$this->expectExceptionMessageRegExp('/essage$/');
$this->expectExceptionCode(123);
// code that throws an exception
throw new InvalidArgumentException('message', 123);
}
public function testAnotherException()
{
// repeat as needed
$this->expectException(Exception::class);
throw new Exception('Oh no!');
}
}
Документацию можно найти здесь .
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
Будьте очень осторожны "/**"
, обратите внимание на двойное «*». Запись только «**» (звездочка) приведет к сбою вашего кода. Также убедитесь, что вы используете последнюю версию phpUnit. В некоторых более ранних версиях phpunit @expectedException Exception не поддерживается. У меня был 4.0, и он не работал для меня, мне пришлось обновить до 5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer, чтобы обновить с помощью composer.
Для PHPUnit 5.7.27 и PHP 5.6, а также для тестирования нескольких исключений в одном тесте важно было принудительно выполнить тестирование исключений. Использование только обработки исключений для утверждения экземпляра Exception пропустит тестирование ситуации, если исключение не происходит.
public function testSomeFunction() {
$e=null;
$targetClassObj= new TargetClass();
try {
$targetClassObj->doSomething();
} catch ( \Exception $e ) {
}
$this->assertInstanceOf(\Exception::class,$e);
$this->assertEquals('Some message',$e->getMessage());
$e=null;
try {
$targetClassObj->doSomethingElse();
} catch ( Exception $e ) {
}
$this->assertInstanceOf(\Exception::class,$e);
$this->assertEquals('Another message',$e->getMessage());
}
function yourfunction($a,$z){
if($a<$z){ throw new <YOUR_EXCEPTION>; }
}
вот тест
class FunctionTest extends \PHPUnit_Framework_TestCase{
public function testException(){
$this->setExpectedException(<YOUR_EXCEPTION>::class);
yourfunction(1,2);//add vars that cause the exception
}
}
PhpUnit - удивительная библиотека, но этот конкретный момент немного расстраивает. Вот почему мы можем использовать открытую библиотеку turbotesting-php, которая имеет очень удобный метод утверждения, чтобы помочь нам тестировать исключения. Это найдено здесь:
И чтобы использовать это, мы просто сделали бы следующее:
AssertUtils::throwsException(function(){
// Some code that must throw an exception here
}, '/expected error message/');
Если код, который мы вводим внутри анонимной функции, не генерирует исключение, оно будет выброшено.
Если код, который мы печатаем внутри анонимной функции, выдает исключение, но его сообщение не соответствует ожидаемому регулярному выражению, исключение также будет выдано.