PhpUnit Testing multiple return stub method
I am testing PHPUnit with symfony2. I have a problem with one specific test.
I am testing the response form for one of my classes, of course one answer is true one false. I have a Mock of my database and I have a stub for one of the methods from my databaseRepository.
The problem is that in one test I am stubbing a method with a valid array, in the second test I just want the request to be invalid.
my db MOck:
//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);
So, I try to have two different expectations, but this obvious one doesn't work ..... is it possible for the stub method to have two different results.?
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);
}
}
source to share
You can do this in a variety of ways.
Here are two ways that might suit your needs.
1 - Move getRecord () waits for tests
/**
* @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));
}
As you can see, there are many duplicates, so use dataprovider .
2 - Using @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));
}
Using @dataProvider you can use as many values ββas you want to check all cases.
source to share
I think you should use PHPUnit method at()
to test the method call at a specific index. Therefore, you must substitute the value argument with the expects
correct index pointer.
So, you can use the following code:
//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/
Hope for this help
source to share