Alguém sabe se existe assert
ou algo assim que pode testar se uma exceção foi lançada no código que está sendo testado?
Alguém sabe se existe assert
ou algo assim que pode testar se uma exceção foi lançada no código que está sendo testado?
Respostas:
<?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);
}
}
documentação do expectException () PHPUnit
O artigo do autor do PHPUnit fornece explicação detalhada sobre o teste das melhores práticas de exceções.
$this->setExpectedException('\My\Name\Space\MyCustomException');
setExpectedException
método foi descontinuado e substituído pelo expectException
. :)
expectException()
. Embora possa ter sido óbvio para alguns, era uma pegadinha para mim.
Você também pode usar uma anotação de docblock até que o PHPUnit 9 seja lançado:
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
Para o PHP 5.5+ (especialmente com código no namespace), agora eu prefiro usar ::class
IncorrectPasswordException
deve ser suficiente - para que a mensagem "Wrong password for bob@me.com"
seja igual a auxiliar. Acrescente a isso que você deseja gastar o menor tempo possível escrevendo testes e comece a ver a importância dos testes simples.
Se você estiver executando o PHP 5.5+, poderá usar a ::class
resolução para obter o nome da classe com expectException
/setExpectedException
. Isso fornece vários benefícios:
string
para que ele funcione com qualquer versão do PHPUnit.Exemplo:
namespace \My\Cool\Package;
class AuthTest extends \PHPUnit_Framework_TestCase
{
public function testLoginFailsForWrongPassword()
{
$this->expectException(WrongPasswordException::class);
Auth::login('Bob', 'wrong');
}
}
Compilações PHP
WrongPasswordException::class
para dentro
"\My\Cool\Package\WrongPasswordException"
sem PHPUnit ser o mais sábio.
Nota : O PHPUnit 5.2 foi introduzido
expectException
como um substituto parasetExpectedException
.
O código abaixo testará a mensagem de exceção e o código de exceção.
Importante: Ele falhará se a exceção esperada também não for lançada.
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()
não é para ser usado dessa maneira, não acho, pelo menos não atualmente (PHPUnit 3.6.11); atua como uma exceção em si. Usando seu exemplo, se $this->fail("Expected exception not thrown")
for chamado, o catch
bloco será acionado e $e->getMessage()
será "Exceção esperada não lançada" .
fail
provavelmente pertence após o bloco catch, não dentro da tentativa.
fail
não deve estar no try
bloco. Ele, por si só, aciona o catch
bloco, produzindo resultados falsos.
catch(Exception $e)
. Este método funciona muito bem para mim quando eu tento capturar exceções específicas:try { throw new MySpecificException; $this->fail('MySpecificException not thrown'); } catch(MySpecificException $e){}
Você pode usar a extensão assertException para afirmar mais de uma exceção durante a execução de um teste.
Insira o método no seu TestCase e use:
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}
Eu também fiz uma característica para os amantes do bom código ..
assertException
está definido. Também não consigo encontrá-lo no manual do PHPUnit.
asertException
método não faz parte do PHPUnit original. Você deve herdar a PHPUnit_Framework_TestCase
classe e adicionar o método vinculado na postagem acima manualmente. Seus casos de teste herdarão essa classe herdada.
Uma maneira alternativa pode ser a seguinte:
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');
Verifique se a sua classe de teste se estende \PHPUnit_Framework_TestCase
.
O expectException
método PHPUnit é muito inconveniente, pois permite testar apenas uma exceção por método de teste.
Eu fiz essa função auxiliar para afirmar que alguma função lança uma exceção:
/**
* 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');
}
Adicione-o à sua classe de teste e chame desta maneira:
public function testSomething() {
$this->assertException(\PDOException::class, function() {
new \PDO('bad:param');
});
$this->assertException(\PDOException::class, function() {
new \PDO('foo:bar');
});
}
As " melhores práticas " atuais do PHPUnit para testes de exceção parecem .. sem brilho ( docs ).
Como eu queria mais do que a expectException
implementação atual , criei uma característica para usar nos meus casos de teste. São apenas ~ 50 linhas de código .
assert
Sintaxe padrãoassertNotThrows
Throwable
erros do PHP 7Publiquei o AssertThrows
traço no Github e no packagist para que ele possa ser instalado com o compositor.
Apenas para ilustrar o espírito por trás da sintaxe:
<?php
// Using simple callback
$this->assertThrows(MyException::class, [$obj, 'doSomethingBad']);
// Using anonymous function
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
Muito arrumado?
Veja abaixo um exemplo de uso mais abrangente:
<?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...)
, inverter como no seu exemplo, por isso deveria ser$this->assertEquals("Exception message", $ex->getMessage());
Aqui estão todas as asserções de exceção que você pode fazer. Observe que todos eles são opcionais .
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!');
}
}
A documentação pode ser encontrada aqui .
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
Tenha muito cuidado "/**"
, observe o duplo "*". Escrever apenas "**" (asterix) falhará no seu código. Certifique-se também de usar a última versão do phpUnit. Em algumas versões anteriores do phpunit @expectedException Exception não é suportado. Eu tinha 4.0 e não funcionou para mim, tive que atualizar para 5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer para atualizar com o compositor.
Para o PHPUnit 5.7.27 e PHP 5.6 e para testar várias exceções em um teste, era importante forçar o teste de exceção. Usar o tratamento de exceções sozinho para afirmar a instância de Exceção ignorará o teste da situação se nenhuma exceção ocorrer.
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>; }
}
aqui está o teste
class FunctionTest extends \PHPUnit_Framework_TestCase{
public function testException(){
$this->setExpectedException(<YOUR_EXCEPTION>::class);
yourfunction(1,2);//add vars that cause the exception
}
}
PhpUnit é uma biblioteca incrível, mas esse ponto específico é um pouco frustrante. É por isso que podemos usar a biblioteca opensource turbotesting-php, que possui um método de asserção muito conveniente para nos ajudar a testar exceções. Pode ser encontrada aqui:
E, para usá-lo, basta fazer o seguinte:
AssertUtils::throwsException(function(){
// Some code that must throw an exception here
}, '/expected error message/');
Se o código digitado dentro da função anônima não gerar uma exceção, uma exceção será lançada.
Se o código que digitarmos dentro da função anônima gerar uma exceção, mas sua mensagem não corresponder ao regexp esperado, uma exceção também será lançada.