PHPUnit:如何在类上模拟函数?
我有一个叫做“QueryService”的类。在这个类中,有一个名为“GetErrorCode”的函数。这个类上还有一个名为“DoQuery”的函数。所以你可以放心地说,我有这样的东西:PHPUnit:如何在类上模拟函数?,php,mocking,phpunit,Php,Mocking,Phpunit,我有一个叫做“QueryService”的类。在这个类中,有一个名为“GetErrorCode”的函数。这个类上还有一个名为“DoQuery”的函数。所以你可以放心地说,我有这样的东西: class QueryService { function DoQuery($request) { $svc = new IntegratedService(); $result = $svc->getResult($request); if ($r
class QueryService {
function DoQuery($request) {
$svc = new IntegratedService();
$result = $svc->getResult($request);
if ($result->success == false)
$result->error = $this->GetErrorCode($result->errorCode);
}
function GetErrorCode($errorCode) {
// do stuff
}
}
public function testDoQuery()
{
$queryService = $this->getMock('\QueryService', array('GetErrorCode')); // this will mock only "GetErrorCode" method
$queryService->expects($this->once())
->method('GetErrorCode')
->with($this->equalTo($expectedErrorCode));
}
public function testDoQuery_Error()
{
$integratedService = $this->getMock('\IntegratedService', array('getResult'));
$expectedResult = new \Result;
$expectedResult->success = false;
$integratedService->expects($this->any())
->method('getResult')
->will($this->returnValue($expectedResult));
$queryService = $this->getMockBuilder('\QueryService')
->setMethods(array('GetErrorCode'))
->setConstructorArgs(array($integratedService))
->getMock();
$queryService->expects($this->once())
->method('GetErrorCode')
->with($this->equalTo($expectedErrorCode))
->will($this->returnValue('expected error msg');
$this->assertEquals($expectedResult->error, 'expected error msg');
}
public function testDoQuery_Success()
{
$integratedService = $this->getMock('\IntegratedService', array('getResult'));
$expectedResult = new \Result;
$expectedResult->success = true;
$integratedService->expects($this->any())
->method('getResult')
->will($this->returnValue($expectedResult));
$queryService = $this->getMockBuilder('\QueryService')
->setMethods(array('GetErrorCode'))
->setConstructorArgs(array($integratedService))
->getMock();
$queryService->expects($this->never())
->method('GetErrorCode');
}
我想创建一个phpunit测试来测试“DoQuery”。但是,我希望“GetErrorCode”的结果由模拟确定。换句话说,我想说,如果$errorCode=1,GetErrorCode必须绕过此函数中的任何逻辑,只返回单词“ONE”。如果是除1以外的任何数字,则必须返回“否”
如何使用PHPUNIT mock设置该类?要测试该类,您需要模拟
IntegratedService
。然后,可以将IntegratedService::getResult()
设置为在模拟中返回您喜欢的内容
然后测试就变得容易了。您还需要能够使用依赖项注入来传递模拟服务,而不是真正的服务
类别:
class QueryService {
private $svc;
// Constructor Injection, pass the IntegratedService object here
public function __construct($Service = NULL)
{
if(! is_null($Service) )
{
if($Service instanceof IntegratedService)
{
$this->SetIntegratedService($Service);
}
}
}
function SetIntegratedService(IntegratedService $Service)
{
$this->svc = $Service
}
function DoQuery($request) {
$svc = $this->svc;
$result = $svc->getResult($request);
if ($result->success == false)
$result->error = $this->GetErrorCode($result->errorCode);
}
function GetErrorCode($errorCode) {
// do stuff
}
}
测试:
要测试这个类,您需要模拟
IntegratedService
。然后,可以将IntegratedService::getResult()
设置为在模拟中返回您喜欢的内容
然后测试就变得容易了。您还需要能够使用依赖项注入来传递模拟服务,而不是真正的服务
类别:
class QueryService {
private $svc;
// Constructor Injection, pass the IntegratedService object here
public function __construct($Service = NULL)
{
if(! is_null($Service) )
{
if($Service instanceof IntegratedService)
{
$this->SetIntegratedService($Service);
}
}
}
function SetIntegratedService(IntegratedService $Service)
{
$this->svc = $Service
}
function DoQuery($request) {
$svc = $this->svc;
$result = $svc->getResult($request);
if ($result->success == false)
$result->error = $this->GetErrorCode($result->errorCode);
}
function GetErrorCode($errorCode) {
// do stuff
}
}
测试:
您需要使用
PHPUnit
创建测试对象。如果您告诉PHPUnit
您想要模拟它的方法,那么只模拟这些方法,其余的类方法将与原始类保持一致
因此,示例测试可以如下所示:
class QueryService {
function DoQuery($request) {
$svc = new IntegratedService();
$result = $svc->getResult($request);
if ($result->success == false)
$result->error = $this->GetErrorCode($result->errorCode);
}
function GetErrorCode($errorCode) {
// do stuff
}
}
public function testDoQuery()
{
$queryService = $this->getMock('\QueryService', array('GetErrorCode')); // this will mock only "GetErrorCode" method
$queryService->expects($this->once())
->method('GetErrorCode')
->with($this->equalTo($expectedErrorCode));
}
public function testDoQuery_Error()
{
$integratedService = $this->getMock('\IntegratedService', array('getResult'));
$expectedResult = new \Result;
$expectedResult->success = false;
$integratedService->expects($this->any())
->method('getResult')
->will($this->returnValue($expectedResult));
$queryService = $this->getMockBuilder('\QueryService')
->setMethods(array('GetErrorCode'))
->setConstructorArgs(array($integratedService))
->getMock();
$queryService->expects($this->once())
->method('GetErrorCode')
->with($this->equalTo($expectedErrorCode))
->will($this->returnValue('expected error msg');
$this->assertEquals($expectedResult->error, 'expected error msg');
}
public function testDoQuery_Success()
{
$integratedService = $this->getMock('\IntegratedService', array('getResult'));
$expectedResult = new \Result;
$expectedResult->success = true;
$integratedService->expects($this->any())
->method('getResult')
->will($this->returnValue($expectedResult));
$queryService = $this->getMockBuilder('\QueryService')
->setMethods(array('GetErrorCode'))
->setConstructorArgs(array($integratedService))
->getMock();
$queryService->expects($this->never())
->method('GetErrorCode');
}
无论如何,正如上面的答案所说,您还应该使用依赖注入
模式,以使模拟集成服务
成为可能(因为根据上面的示例,您需要知道$result->success
值)
因此,正确的测试应该如下所示:
class QueryService {
function DoQuery($request) {
$svc = new IntegratedService();
$result = $svc->getResult($request);
if ($result->success == false)
$result->error = $this->GetErrorCode($result->errorCode);
}
function GetErrorCode($errorCode) {
// do stuff
}
}
public function testDoQuery()
{
$queryService = $this->getMock('\QueryService', array('GetErrorCode')); // this will mock only "GetErrorCode" method
$queryService->expects($this->once())
->method('GetErrorCode')
->with($this->equalTo($expectedErrorCode));
}
public function testDoQuery_Error()
{
$integratedService = $this->getMock('\IntegratedService', array('getResult'));
$expectedResult = new \Result;
$expectedResult->success = false;
$integratedService->expects($this->any())
->method('getResult')
->will($this->returnValue($expectedResult));
$queryService = $this->getMockBuilder('\QueryService')
->setMethods(array('GetErrorCode'))
->setConstructorArgs(array($integratedService))
->getMock();
$queryService->expects($this->once())
->method('GetErrorCode')
->with($this->equalTo($expectedErrorCode))
->will($this->returnValue('expected error msg');
$this->assertEquals($expectedResult->error, 'expected error msg');
}
public function testDoQuery_Success()
{
$integratedService = $this->getMock('\IntegratedService', array('getResult'));
$expectedResult = new \Result;
$expectedResult->success = true;
$integratedService->expects($this->any())
->method('getResult')
->will($this->returnValue($expectedResult));
$queryService = $this->getMockBuilder('\QueryService')
->setMethods(array('GetErrorCode'))
->setConstructorArgs(array($integratedService))
->getMock();
$queryService->expects($this->never())
->method('GetErrorCode');
}
您需要使用
PHPUnit
创建测试对象。如果您告诉PHPUnit
您想要模拟它的方法,那么只模拟这些方法,其余的类方法将与原始类保持一致
因此,示例测试可以如下所示:
class QueryService {
function DoQuery($request) {
$svc = new IntegratedService();
$result = $svc->getResult($request);
if ($result->success == false)
$result->error = $this->GetErrorCode($result->errorCode);
}
function GetErrorCode($errorCode) {
// do stuff
}
}
public function testDoQuery()
{
$queryService = $this->getMock('\QueryService', array('GetErrorCode')); // this will mock only "GetErrorCode" method
$queryService->expects($this->once())
->method('GetErrorCode')
->with($this->equalTo($expectedErrorCode));
}
public function testDoQuery_Error()
{
$integratedService = $this->getMock('\IntegratedService', array('getResult'));
$expectedResult = new \Result;
$expectedResult->success = false;
$integratedService->expects($this->any())
->method('getResult')
->will($this->returnValue($expectedResult));
$queryService = $this->getMockBuilder('\QueryService')
->setMethods(array('GetErrorCode'))
->setConstructorArgs(array($integratedService))
->getMock();
$queryService->expects($this->once())
->method('GetErrorCode')
->with($this->equalTo($expectedErrorCode))
->will($this->returnValue('expected error msg');
$this->assertEquals($expectedResult->error, 'expected error msg');
}
public function testDoQuery_Success()
{
$integratedService = $this->getMock('\IntegratedService', array('getResult'));
$expectedResult = new \Result;
$expectedResult->success = true;
$integratedService->expects($this->any())
->method('getResult')
->will($this->returnValue($expectedResult));
$queryService = $this->getMockBuilder('\QueryService')
->setMethods(array('GetErrorCode'))
->setConstructorArgs(array($integratedService))
->getMock();
$queryService->expects($this->never())
->method('GetErrorCode');
}
无论如何,正如上面的答案所说,您还应该使用依赖注入
模式,以使模拟集成服务
成为可能(因为根据上面的示例,您需要知道$result->success
值)
因此,正确的测试应该如下所示:
class QueryService {
function DoQuery($request) {
$svc = new IntegratedService();
$result = $svc->getResult($request);
if ($result->success == false)
$result->error = $this->GetErrorCode($result->errorCode);
}
function GetErrorCode($errorCode) {
// do stuff
}
}
public function testDoQuery()
{
$queryService = $this->getMock('\QueryService', array('GetErrorCode')); // this will mock only "GetErrorCode" method
$queryService->expects($this->once())
->method('GetErrorCode')
->with($this->equalTo($expectedErrorCode));
}
public function testDoQuery_Error()
{
$integratedService = $this->getMock('\IntegratedService', array('getResult'));
$expectedResult = new \Result;
$expectedResult->success = false;
$integratedService->expects($this->any())
->method('getResult')
->will($this->returnValue($expectedResult));
$queryService = $this->getMockBuilder('\QueryService')
->setMethods(array('GetErrorCode'))
->setConstructorArgs(array($integratedService))
->getMock();
$queryService->expects($this->once())
->method('GetErrorCode')
->with($this->equalTo($expectedErrorCode))
->will($this->returnValue('expected error msg');
$this->assertEquals($expectedResult->error, 'expected error msg');
}
public function testDoQuery_Success()
{
$integratedService = $this->getMock('\IntegratedService', array('getResult'));
$expectedResult = new \Result;
$expectedResult->success = true;
$integratedService->expects($this->any())
->method('getResult')
->will($this->returnValue($expectedResult));
$queryService = $this->getMockBuilder('\QueryService')
->setMethods(array('GetErrorCode'))
->setConstructorArgs(array($integratedService))
->getMock();
$queryService->expects($this->never())
->method('GetErrorCode');
}