3

私は最近、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 が実際に配列を返すことを保証する方法と、これをテストする方法がわかりません。私が理解しているように、テストを成功させるコードを実装するまで、最初はテストが失敗するはずです。しかし、このテストでは、ほとんどが明らかに間違っていますが、常にパスします。これは、テストから理解できる値をすべて取り除きます。

そのような方法を実際にテストする方法の例をいくつか教えていただければ幸いです。

4

2 に答える 2

2

SoapWrap私はあなたの質問の例を 100% 把握しているわけではありませんが、正しく理解している場合は、ユニットをテストしたいと考えてSoapClientおり、共同作業者として持っています。

これで、配列を返す場合のテストを作成するSoapWrap::getStations()と (実際には常に実行されます)、テストは常にパスします。したがって、失敗したテストが実装されるまでの最初の質問については (テスト駆動開発 (TDD) のように: テストが失敗する (赤); 合格するまで必要なコードだけを書く (黄色 (または: 緑)));コード(緑(または:青)))、しかしあなたは間違った方法でそれをしました。コードを記述する前にテストを記述しておく必要があります。たとえば、最初にテストを呼び出すと、PHPunit はSoapWrapクラスが見つからないという致命的なエラーでクラッシュし、まだ記述されていないためインスタンス化できません。

したがって、今すぐ削除して、これまでに行ったコードを忘れるようにしてください。テストを再実行して失敗することを確認してから、新しく書き直してください。

その前にのクラスも単体テストしたことを確認してください$StationFilter

モッキングに関するあなたの質問の 2 番目の部分について: あなたは共同作業者をあざけっていますが、ここではおそらくSoapClient::GetStations()メソッドです。これにより、実際に SOAP 経由でリモート リクエストを実行する手間が省けます。それはもう簡単です。共同作業者をモックして、ユニットをテストします。

于 2013-09-25T19:07:43.007 に答える
0

これは、作成した Web サービスを試してみるのに役立つかもしれません。このアプリで転送されるデータをシミュレートしてみることができます。ここをチェックしてください http://www.soapui.org/

ありがとうございます、 ジャニトラ・パンジー

于 2013-09-25T18:47:57.997 に答える