Замена конструкций exit/die в unit-тестах
Если в коде вы используете die/exit то PHPUnit прекратит свою работу в этот момент. Для этого нам нужно заменить конструкцию exit
или die
. Но это сделать сложно т.к. Functions Mocker с этим не справляется.
Пример:
class Duck {
public function last_words() {
die( 'I\'ll be back' );
}
}
Меняем класс следующий образом:
class Duck {
public function last_words() {
return $this->die( 'I\'ll be back' );
}
/**
* @codeCoverageIgnore
*/
protected function die( $message = '' ) {
return die( $message );
}
}
Добавляем к методу die()
аннотацию @codeCoverageIgnore
, чтобы не учитывать при вычислении покрытия тестов
Вместо реального объекта создаем частичного двойника. Затем разрешаем вызов защищенных методов и делаем заглушку для метода die()
:
use PHPUnit\Framework\TestCase;
class Test_Duck extends TestCase {
public function test_last_words() {
$duck = \Mockery::mock( Duck::class )->makePartial();
$duck->shouldAllowMockingProtectedMethods();
$duck
->shouldReceive( 'die' )
->with( 'I\'ll be back' )
->once()
->andReturnArg( 0 );
$this->assertSame( 'I\'ll be back', $duck->last_words() );
}
}
Это нам может понадобиться после использования редиректов в WordPress, например wp_safe_redirect
:
class Some_Class {
public function some_method() {
wp_safe_redirect(
remove_query_arg(
[ '_wp_http_referer', '_wpnonce' ],
wp_unslash( $_SERVER['REQUEST_URI'] ) // phpcs:ignore
)
);
$this->exit();
}
/**
* @codeCoverageIgnore
*/
protected function exit() {
exit;
}
}
И собственно весь тест для этого кода:
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
class Test_Some_Class extends TestCase {
public function test_some_method() {
$some_url = '/some-url/';
$some_class = \Mockery::mock( \Some_Class::class )->makePartial();
$some_class->shouldAllowMockingProtectedMethods();
$some_class
->shouldReceive( 'exit' )
->once();
$_REQUEST['_wp_http_referer'] = 'some-referer';
$_SERVER['REQUEST_URI'] = $some_url;
expect( 'wp_safe_redirect' )
->with( $some_url )
->once();
expect( 'remove_query_arg' )
->with(
[ '_wp_http_referer', '_wpnonce' ],
$some_url
)
->once()
->andReturn( $some_url );
expect( 'wp_unslash' )
->with(
$some_url
)
->once()
->andReturn( $some_url );
$some_class->some_method();
}
}
Источник: WP Punk.