Как тест удваивается, помогите мне протестировать устройство, которое взаимодействует с веб-сервисом SOAP через SoapClient


Недавно я начал свое путешествие по тестированию на 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, ни SoapWrap, поскольку он использует SoapClient в качестве зависимого. Двойная обертка мыла вызвана вызовом ->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 действительно возвращает массив, и как я должен это проверить. Насколько я понимаю, мой тест должен сначала завершиться неудачей, пока я не внедрю код, который позволит ему пройти. Но с этим тестом, который, скорее всего, будет явно неправильным, он всегда проходит. Что лишает меня любого значения, которое я могу понять из теста.

Я надеюсь, что вы можете помочь мне с некоторыми примерами того, как действительно протестировать такой метод.

Author: hakre, 2013-09-25

2 answers

Я не на 100% понимаю пример в вашем вопросе, однако, если я правильно понимаю, вы хотите протестировать модуль SoapWrap, и у него есть SoapClient в качестве соавтора.

Теперь, когда вы создаете тест, если SoapWrap::getStations() возвращает массив - что на самом деле всегда происходит - тест всегда будет пройден. Итак, для вашего первого вопроса о неудачном тесте, пока он не будет реализован (как в тестовой разработке (TDD): Тест завершается неудачно (Красный); Напишите как можно меньше кода, пока он не пройдет (Желтый (или: Зеленый)); Измените код (зеленый (или: Синий))), но вы сделали это неправильно. Вы должны были написать тест до написания кода, например, при первом вызове теста PHPUnit должен аварийно завершить работу с фатальной ошибкой, что класс SoapWrap не найден и не может быть создан, потому что до сих пор он не был написан.

Так что удалите его сейчас и постарайтесь забыть код, который вы сделали до сих пор, повторите тест, чтобы увидеть, что он не удался, а затем напишите его заново.

Убедитесь, что вы провели модульное тестирование класса $StationFilter до и это тоже.

Что касается второй части вашего вопроса о насмешках: Вы издеваетесь над сотрудниками, здесь, скорее всего, метод SoapClient::GetStations(). Это избавит вас от необходимости фактически запускать удаленный запрос через SOAP. Это уже так просто. Вы издеваетесь над сотрудниками, чтобы протестировать устройство.

 2
Author: hakre, 2013-09-25 19:07:43

Возможно, это поможет вам опробовать созданный вами веб-сервис, вы можете попробовать смоделировать данные, передаваемые с помощью этого приложения. Проверьте здесь http://www.soapui.org/

Спасибо и с уважением, Джанитра Панджи

 0
Author: Janitra Panji, 2013-09-25 18:47:57