Хтось знає, чи є 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);
}
}
очікуємоException () документації PHPUnit
Стаття автора PHPUnit надає детальне пояснення щодо тестування найкращих практик винятків.
$this->setExpectedException('\My\Name\Space\MyCustomException');
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
ймовірно, належить після блоку лову, а не всередині спроби.
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 та пакувальнику, щоб її можна було встановити разом із композитором.
Просто для ілюстрації духу за синтаксисом:
<?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()
є 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 Виняток не підтримується. У мене було 4.0, і це не спрацювало для мене, мені довелося оновити до 5,5 https://coderwall.com/p/mklvdw/install-phpunit-with-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/');
Якщо код, який ми вводимо всередині анонімної функції, не виключає виключення, буде викинуто виняток.
Якщо код, який ми вводимо всередині анонімної функції, видає виняток, але його повідомлення не відповідає очікуваному регулярному вираженню, також буде викинуто виняток.