PhpUnit 测试存根方法多个 return
PhpUnit Testing stub method multiple return
我正在用 symfony2 做一些 PHPUnit 测试。我在一项特定测试中遇到问题。
我正在测试来自我的一个 Class 的响应,当然一个响应是正确的,一个是错误的。我有一个我的数据库的模拟,并且我有一个来自我的 databaseRepository 的方法的存根。
问题是,在一个测试中,我对具有有效数组的方法进行了存根,在第二个测试中,我只想查询无效的 null。
我的数据库 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);
所以我试图有两个不同的期望,但是这显然行不通.....是否有可能有一个存根方法有两个不同的 returns..?
测试 1:
<?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);
}
}
您可以通过多种方式做到这一点。
这里有两种方法可能适合您的需要。
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,您可以使用任意数量的值来测试所有情况。
我认为您应该使用 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/
希望对您有所帮助
我正在用 symfony2 做一些 PHPUnit 测试。我在一项特定测试中遇到问题。
我正在测试来自我的一个 Class 的响应,当然一个响应是正确的,一个是错误的。我有一个我的数据库的模拟,并且我有一个来自我的 databaseRepository 的方法的存根。
问题是,在一个测试中,我对具有有效数组的方法进行了存根,在第二个测试中,我只想查询无效的 null。
我的数据库 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);
所以我试图有两个不同的期望,但是这显然行不通.....是否有可能有一个存根方法有两个不同的 returns..?
测试 1:
<?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);
}
}
您可以通过多种方式做到这一点。
这里有两种方法可能适合您的需要。
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,您可以使用任意数量的值来测试所有情况。
我认为您应该使用 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/
希望对您有所帮助