PHPでrequestBodyがapplication/www-xxx以外のリクエスト(JSONとかXML)を処理する場合、
php://input
からデータを取得することになります。
昨今のフレームワークであればリクエストに関するデータらはRequestオブジェクトなどに隠蔽されており、functional tests等でモックできるため
php://input
を意識することはほとんど無いと思います。
ただ、フレームワークを使わない場合は php://input
を直接ハンドリングする必要があるのですが、その場合functional testsでは php://input
のモックをする必要があります。
ということで今回は php://input
をstreamWrapperでモックしてphpunitでテストする方法について紹介します。
以下のようなstreamWrapperなクラスを作ります。
<?php
class PHPStreamWrapper
{
private static $content;
private $position;
/**
* @param string $content
*/
public static function setContent($content)
{
self::$content = $content;
}
public function stream_open($path)
{
return true;
}
public function stream_read($count)
{
$ret = substr(self::$content, $this->position, $count);
$this->position += strlen($ret);
return $ret;
}
public function stream_stat()
{
return [];
}
public function stream_eof()
{
return $this->position >= strlen(self::$content);
}
}
setContentはモックする文字列をセットする関数で、それ以外はphp://input
からの読み込みで使う関数になります。
基本的にはsetContentでセットした文字列をstream_readで返していくだけ。
あとはsetUpでstream_wrapper_registerして、tearDownでstream_wrapper_restoreして元のストリーム処理に戻せばOK。
<?php
class HogeTest extends PHPUnit\Framework\TestCase
{
public function setUp()
{
stream_wrapper_unregister('php');
stream_wrapper_register('php', PHPStreamWrapper::class);
}
public function tearDown()
{
stream_wrapper_restore('php');
}
public function xxx()
{
PHPStreamWrapper::setContent('mock string');
// 何かテスト
}
}