Adakah yang tahu apakah ada assert
atau sesuatu seperti itu yang dapat menguji apakah pengecualian dilemparkan ke dalam kode yang sedang diuji?
Adakah yang tahu apakah ada assert
atau sesuatu seperti itu yang dapat menguji apakah pengecualian dilemparkan ke dalam kode yang sedang diuji?
Jawaban:
<?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);
}
}
expectException () dokumentasi PHPUnit
Artikel penulis PHPUnit memberikan penjelasan terperinci tentang pengujian pengecualian praktik terbaik.
$this->setExpectedException('\My\Name\Space\MyCustomException');
setExpectedException
sudah usang, diganti dengan yang expectException
satu. :)
expectException()
. Sementara itu mungkin sudah jelas untuk beberapa, itu adalah Gotcha bagi saya.
Anda juga dapat menggunakan anotasi docblock hingga PHPUnit 9 dirilis:
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
Untuk PHP 5.5+ (terutama dengan kode namespaced), saya sekarang lebih suka menggunakan ::class
IncorrectPasswordException
harus cukup - bahwa pesan yang sama "Wrong password for bob@me.com"
adalah tambahan. Tambahkan bahwa Anda ingin menghabiskan sedikit waktu menulis tes mungkin, dan Anda mulai melihat betapa pentingnya tes sederhana menjadi.
Jika Anda menggunakan PHP 5.5+, Anda bisa menggunakan ::class
resolusi untuk mendapatkan nama kelas dengan expectException
/setExpectedException
. Ini memberikan beberapa manfaat:
string
jadi itu akan bekerja dengan versi PHPUnit.Contoh:
namespace \My\Cool\Package;
class AuthTest extends \PHPUnit_Framework_TestCase
{
public function testLoginFailsForWrongPassword()
{
$this->expectException(WrongPasswordException::class);
Auth::login('Bob', 'wrong');
}
}
Kompilasi PHP
WrongPasswordException::class
ke
"\My\Cool\Package\WrongPasswordException"
tanpa PHPUnit menjadi lebih bijak.
Catatan : PHPUnit 5.2 diperkenalkan
expectException
sebagai penggantisetExpectedException
.
Kode di bawah ini akan menguji pesan pengecualian dan kode pengecualian.
Penting: Ini akan gagal jika pengecualian yang diharapkan tidak dibuang juga.
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()
tidak dimaksudkan untuk digunakan dengan cara ini saya tidak berpikir, setidaknya saat ini (PHPUnit 3.6.11); itu bertindak sebagai pengecualian itu sendiri. Menggunakan contoh, jika $this->fail("Expected exception not thrown")
disebut, maka catch
blok dipicu dan $e->getMessage()
yang "diharapkan pengecualian tidak dilempar" .
fail
mungkin milik setelah blok tangkap, bukan di dalam coba.
fail
tidak boleh di try
blok. Itu sendiri memicu catch
blok menghasilkan hasil yang salah.
catch(Exception $e)
. Metode ini bekerja cukup baik untuk saya ketika saya mencoba menangkap Pengecualian tertentu:try { throw new MySpecificException; $this->fail('MySpecificException not thrown'); } catch(MySpecificException $e){}
Anda dapat menggunakan ekstensi assertException untuk menegaskan lebih dari satu pengecualian selama satu pengujian dijalankan.
Masukkan metode ke dalam TestCase Anda dan gunakan:
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}
Saya juga membuat sifat untuk pecinta kode yang bagus ..
assertException
definisi. Saya juga tidak dapat menemukannya di manual PHPUnit.
asertException
Metode bukan bagian dari PHPUnit asli. Anda harus mewarisi PHPUnit_Framework_TestCase
kelas dan menambahkan metode yang ditautkan dalam posting di atas secara manual. Kasing uji Anda akan mewarisi kelas warisan ini.
Cara alternatif bisa sebagai berikut:
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');
Harap pastikan bahwa kelas tes Anda meluas \PHPUnit_Framework_TestCase
.
expectException
Metode PHPUnit sangat merepotkan karena memungkinkan untuk menguji hanya satu pengecualian per metode pengujian.
Saya telah membuat fungsi pembantu ini untuk menyatakan bahwa beberapa fungsi melempar pengecualian:
/**
* 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');
}
Tambahkan ke kelas tes Anda dan panggil seperti ini:
public function testSomething() {
$this->assertException(\PDOException::class, function() {
new \PDO('bad:param');
});
$this->assertException(\PDOException::class, function() {
new \PDO('foo:bar');
});
}
" Praktik terbaik " PHPUnit saat ini untuk pengujian pengecualian tampaknya .. kurang bersemangat ( dokumen ).
Karena saya menginginkan lebih dari expectException
implementasi saat ini , saya membuat sifat untuk digunakan pada kasus pengujian saya. Hanya ~ 50 baris kode .
assert
Sintaks standarassertNotThrows
Throwable
kesalahan PHP 7Saya menerbitkan AssertThrows
sifat tersebut ke Github dan pembuat kemasan sehingga dapat diinstal dengan komposer.
Hanya untuk menggambarkan semangat di balik sintaks:
<?php
// Using simple callback
$this->assertThrows(MyException::class, [$obj, 'doSomethingBad']);
// Using anonymous function
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
Cukup rapi?
Silakan lihat di bawah untuk contoh penggunaan yang lebih komprehensif:
<?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()
adalah assertEquals(mixed $expected, mixed $actual...)
, terbalik seperti pada contoh Anda, jadi seharusnya$this->assertEquals("Exception message", $ex->getMessage());
Berikut semua pernyataan pengecualian yang dapat Anda lakukan. Perhatikan bahwa semuanya adalah opsional .
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!');
}
}
Dokumentasi dapat ditemukan di sini .
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
Berhati-hatilah "/**"
, perhatikan ganda "*". Hanya menulis "**" (asterix) yang akan gagal kode Anda. Pastikan juga Anda menggunakan versi terakhir phpUnit. Dalam beberapa versi sebelumnya, phpunit @expectedException Exception tidak didukung. Saya memiliki 4.0 dan tidak berfungsi untuk saya, saya harus memperbarui ke 5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer untuk memperbarui dengan komposer.
Untuk PHPUnit 5.7.27 dan PHP 5.6 dan untuk menguji beberapa pengecualian dalam satu pengujian, penting untuk memaksa pengujian pengecualian. Menggunakan penanganan pengecualian saja untuk menegaskan instance Exception akan melewatkan pengujian situasi jika tidak ada pengecualian yang terjadi.
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>; }
}
ini tesnya
class FunctionTest extends \PHPUnit_Framework_TestCase{
public function testException(){
$this->setExpectedException(<YOUR_EXCEPTION>::class);
yourfunction(1,2);//add vars that cause the exception
}
}
PhpUnit adalah perpustakaan yang luar biasa, tetapi poin khusus ini agak membuat frustrasi. Inilah sebabnya kami dapat menggunakan pustaka opensource php-turbotesting yang memiliki metode pernyataan yang sangat nyaman untuk membantu kami menguji pengecualian. Itu ditemukan di sini:
Dan untuk menggunakannya, kita cukup melakukan hal berikut:
AssertUtils::throwsException(function(){
// Some code that must throw an exception here
}, '/expected error message/');
Jika kode yang kita ketikkan di dalam fungsi anonim tidak memunculkan eksepsi, eksepsi akan dilempar.
Jika kode yang kita ketikkan di dalam fungsi anonim melempar pengecualian, tetapi pesannya tidak cocok dengan regexp yang diharapkan, pengecualian juga akan dibuang.