2015-06-08 2 views
2

Я выполняю тестирование PHPUnit с symfony2. У меня проблема с одним конкретным тестом.PhpUnit Testing stub method multiple return

Я тестирую форму ответа одного из моих классов, конечно, один ответ является истинным одним ложным. У меня есть Mock моей базы данных, и у меня есть заглушка для одного из методов из моего databaseRepository.

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

мой дб Мок:

//Setting up mock of database repository class 
    $this->db = $this->getMockBuilder('DatabaseRepository') 
     ->disableOriginalConstructor() 
     ->getMock(); 

    $this->db->expects($this->any()) 
     ->method('getRecord') 
     ->will($this->returnValue(self::$registrationRecord)); 

    $this->db->expects($this->any()) 
     ->method('getRecord') 
     ->willReturn(null); 

Так что я пытаюсь иметь два разных, но ожидает, что это obviousley не работает ..... возможно иметь метод заглушки иметь два различных возвращается .. ?

test1:

<?php 


class UnsubscribeRegistrationTemplateTest extends \PHPUnit_Framework_TestCase 
{ 

    /** 
    * @var UnsubscribeRegistrationTemplate 
    */ 
    protected $object; 

    /** 
    * @var ValidationClass 
    */ 
    public $validate; 

    /** 
    * @var DatabaseRepository 
    */ 
    public $db; 

    //Database Record Mock 
    public static $registrationRecord = array 
    (
     'rowid' => '96', 
     'unsubscription' => 'N', 
     'updated' => 'BB' 
    ); 

    /** 
    * 
    */ 
    protected function setUp() 
    { 
     //Setting up mock of validation class 
     $this->validate = $this->getMockBuilder('ValidationClass') 
      ->disableOriginalConstructor() 
      ->getMock(); 

     $this->validate->expects($this->any()) 
      ->method('validateInput') 
      ->willReturn(true); 

     //Setting up mock of database repository class 
     $this->db = $this->getMockBuilder('DatabaseRepository') 
      ->disableOriginalConstructor() 
      ->getMock(); 

     $this->db->expects($this->any()) 
      ->method('getRegistrationRecord') 
      ->will($this->returnValue(self::$registrationRecord)); 

     $this->db->expects($this->any()) 
      ->method('getRegistrationRecord') 
      ->will($this->returnValue(null)); 

     $this->db->expects($this->any()) 
      ->method('setPreRegistrationEnquiryUnsubscriptionEnabled') 
      ->willReturn(true); 

     $this->object = $this->createUnsubscribeRegistrationTemplateInstance(); 
    } 

    /** 
    * @return UnsubscribeRegistrationTemplate 
    * 
    */ 
    public function createUnsubscribeRegistrationTemplateInstance() 
    { 
     //initialize Unsubscribe Registration Template 
     return new UnsubscribeRegistrationTemplate 
     (
      $this->validate, 
      $this->db 
     ); 
    } 

    /** 
    * @param array $mapping 
    * @return Request 
    */ 
    public function createRequest(array $mapping) 
    { 
     $request = new Request(); 

     foreach ($mapping as $k =>$v) 
     { 
      $request->query->set($k, $v); 
     } 

     return $request; 
    } 

    /** 
    * 
    */ 
    public function testUnsubscribeRegistrationTemplateValidResponse() 
    { 
     $request = $this->createRequest(array(
      'registration_id' => '96', 
      'source_channel' => 'BB' 
     )); 

     $response = new Response(
      true, 
      'Unsubscription successful' 
     ); 

     $this->assertEquals($response, $this->object->create($request)); 
    } 

    /** 
    * 
    */ 
    public function testUnsubscribeRegistrationTemplateEmptyResponse() 
    { 
     $request = $this->createRequest(array(
      'registration_id' => '96', 
      'source_channel' => 'BB' 
     )); 

     $response = new Response(
      false, 
      'Registration Record Not Found.' 
     ); 

     $this->assertEquals($response, $this->object->create($request)); 
    } 

    /** 
    * 
    */ 
    public function testIsAlreadyRegisteredValidResponse() 
    { 
     //Testing record is already unsubscribed 
     $registrationRecord = array(
      'unsubscription_enabled' => 'Y' 
     ); 

     $this->assertTrue($this->object->isAlreadyUnsubscribed($registrationRecord)); 
    } 

    /** 
    * 
    */ 
    public function testIsAlreadyRegisteredInValidResponse() 
    { 
     //Testing record not unsubscribed 
     $registrationRecord = array(
      'unsubscription_enabled' => 'N' 
     ); 
     $this->assertFalse($this->object->isAlreadyUnsubscribed($registrationRecord)); 
    } 

    /** 
    * 
    */ 
    protected function tearDown() 
    { 
     unset($this->object); 
    } 

} 
+0

Подведите ожидать относительный метод испытаний, в качестве примера, если 'testIsAlreadyRegisteredInValidResponse' хочет что' getRecord 'return null, переместите там код и удалите другой из него. – Matteo

+0

да, я делал это раньше, но функция ожидания была подсвечена моим PhpStorm, и я, хотя это не сработает, поэтому никогда не было привязано к попытке:/теперь я это сделал, и он отлично работает, но php storm hihglights говорит: «Метод не ожидается» в классе databaseRepository – Koper

+0

Не беспокойтесь об этом, только потому, что phpstorm не undestand правильный тип объекта, вероятно, из-за неправильной или отсутствующей аннотации PHPDoc. Так ты решил? – Matteo

ответ

2

Вы можете сделать это во многих отношениях.
Вот два способа, которые могут удовлетворить ваши потребности.

1 - Перемещение getRecord() ожидает испытаний

/** 
* @test 
*/ 
public function ifTrue() 
{ 
    $this->db->expects($this->once()) 
    ->method('getRecord') 
    ->will($this->returnValue(self::$registrationRecord)); 

    $request = $this->createRequest(array(
     'id' => '10', 
     'code' => 'BB' 
    )); 

    $response = new Response(
     true, 
     'successful' 
    ); 

    $this->assertEquals($response, $this->object->create($request)); 
} 

/** 
* @test 
*/ 
public function ifFalse() 
{ 
    $this->db->expects($this->once()) 
    ->method('getRecord') 
    ->willReturn(null); 

    $request = $this->createRequest(array(
     'id' => '10', 
     'code' => 'BB' 
    )); 

    $response = new Response(
     false, 
     'Record Not Found.' 
    ); 

    $this->assertEquals($response, $this->object->create($request)); 
} 

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

2 - Использование @dataProvider

protected function getDataForTest() 
{ 
    return array(
     array(self::$registrationRecord, true, 'successful'), 
     array(null, false, 'Record Not Found.') 
    ); 
} 

/** 
* @dataProvider getDataForTest 
* @test 
*/ 
public function ifTrue($getRecordValue, $bool, $message) 
{ 
    $this->db->expects($this->once()) 
    ->method('getRecord') 
    ->will($this->returnValue($getRecordValue); 

    $request = $this->createRequest(array(
     'id' => '10', 
     'code' => 'BB' 
    )); 

    $response = new Response(
     $bool, 
     $message 
    ); 

    $this->assertEquals($response, $this->object->create($request)); 
} 

Использование @dataProvider вы можете использовать столько значения, сколько вы хотите, чтобы проверить все случаи.

+0

Эй, спасибо за ваш ответ «Я пробовал первый путь, но он тогда говорит: ожидать не найдется в классе – Koper

+0

Где и когда вы инициируете свой dbMock? –

+0

check above Я отредактировал мой вопрос thx – Koper

2

Я думаю, вы должны использовать метод PHPUnit at() для проверки вызова метода по определенному индексу. Поэтому вы должны подставить аргумент значения expects правильным ответом индекса.

Таким образом, вы можете использовать следующий код:

//Setting up mock of database repository class 
$this->db = $this->getMockBuilder('DatabaseRepository') 
    ->disableOriginalConstructor() 
    ->getMock(); 

$this->db->expects($this->at(0)) // Mock the first call 
    ->method('getRecord') 
    ->will($this->returnValue(self::$registrationRecord)); 

$this->db->expects($this->at(1)) // Mock the second call 
    ->method('getRecord') 
    ->willReturn(null); 

http://www.andrejfarkas.com/2012/07/phpunit-at-method-to-check-method-invocation-at-certain-index/

Надеется, что это поможет

+0

Hey thx для вашего повтора. Я действительно пробовал это решение, возможно, должен был упомянуть, но он не работал. У меня было это сообщение: d> при вызове при индексе последовательности 0. Ожидаемый вызов в индексе 0 никогда не был достигнут. – Koper

+0

Утверждение говорит, что в вашем тесте метод никогда не выполнялся – Matteo

+0

@ Koper вы можете разместить весь тестовый класс? – Matteo