私は最近、phpでのテストの旅を始めました。外部サービスをテストする方法と、テスト中のメソッドがテストの約束どおりに実際に動作することを保証するのにスタブがどのように役立つかを理解するのに苦労しています。
次の例は、テスト方法を理解できないコードから取られたものです。問題のコンストラクトとメソッドのみを含めました。
class SoapWrap {
const WDSL_URL = 'http://traindata.dsb.dk/stationdeparture/Service.asmx?WSDL';
/**
* The WDSL/SOAP Client
* @access private
* @var \SoapClient $Client
*/
private $Client; // SOAP client.
/**
* Sets up \SoapClient connection.
* @throws \SoapFault upon SOAP/WDSL error.
*/
public function __construct( \SoapClient $SoapClient )
{
try
{
$this->Client = $SoapClient;
}
catch( \SoapFault $SoapFault )
{
throw $SoapFault;
}
}
/**
* Gets all stations and filters if a filter is passed.
*
* As DSB SOAP service only allows to get all stations
* a filter can be used narrow down the results.
* @param \DSBPHP\Filters\BaseFilter $StationFilte
* @return Array with station value objects.
*/
public function getStations( \DSBPHP\Filters\FilterInterface $StationFilter = null )
{
// DSB soap service inforces only method for getting all stations...
$stations = $this->Client->GetStations()->GetStationsResult->Station;
if($StationFilter !== null)
return $StationFilter->run($stations);
// return all trains
return $stations;
}
}
以下のテストでは、SoapClient を依存関係として使用するため、テストが実際に SoapClient も SoapWrap も使用しないことを保証しようとしました。SoapWrap の double は、上記のコードの getstations() 内の SOAP サービスに対する ->GetStations 呼び出しが原因です。
class SoapWrapTest extends PHPUnit_Framework_TestCase {
private $SoapWrap;
public function setUp()
{
$SoapClient = $this ->getMockBuilder('\SoapClient')
->setMethods(['__construct'])
->disableOriginalConstructor()
->getMock();
$this->SoapWrap = $this ->getMockBuilder('\DSBPHP\App\SoapWrap')
->setMethods(['__construct', 'getStations'])
->disableOriginalConstructor()
->setConstructorArgs([$SoapClient])
->getMock();
}
public function testGetStationsReturnsArray()
{
$this->SoapWrap ->expects($this->once())
->method('getStations')
->will($this->returnValue([]));
$stations = $this->SoapWrap->getStations();
$this->assertInternalType('array', $stations);
}
}
これにより、実際の石鹸サービス SoapWrap が実際に配列を返すことを保証する方法と、これをテストする方法がわかりません。私が理解しているように、テストを成功させるコードを実装するまで、最初はテストが失敗するはずです。しかし、このテストでは、ほとんどが明らかに間違っていますが、常にパスします。これは、テストから理解できる値をすべて取り除きます。
そのような方法を実際にテストする方法の例をいくつか教えていただければ幸いです。