0

「QueryService」というクラスがあります。このクラスには、「GetErrorCode」という関数があります。また、このクラスには「DoQuery」という関数があります。したがって、次のようなものがあると安全に言うことができます。

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
    }
}

「DoQuery」をテストする phpunit テストを作成したいと考えています。ただし、「GetErrorCode」の結果はモックで判定してほしい。つまり、$errorCode = 1 の場合、GetErrorCode はこの関数内のロジックをバイパスし、"ONE" という単語を返す必要があると言いたいのです。1 以外の数値の場合は、"NO" を返す必要があります。

PHPUNIT モックを使用してこれをどのように設定しますか?

4

2 に答える 2

4

このクラスをテストするには、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
    }
}

テスト:

class QueryServiceTest extends PHPUnit_Framework_TestCase
{
    // Simple test for GetErrorCode to work Properly
    public function testGetErrorCode()
    {
        $TestClass = new QueryService();
        $this->assertEquals('One', $TestClass->GetErrorCode(1));
        $this->assertEquals('Two', $TestClass->GetErrorCode(2));
    }

    // Could also use dataProvider to send different returnValues, and then check with Asserts.
    public function testDoQuery()
    {
        // Create a mock for the IntegratedService class,
        // only mock the getResult() method.
        $MockService = $this->getMock('IntegratedService', array('getResult'));

        // Set up the expectation for the getResult() method 
        $MockService->expects($this->any())
                    ->method('getResult')
                    ->will($this->returnValue(1));

        // Create Test Object - Pass our Mock as the service
        $TestClass = new QueryService($MockService);
        // Or
        // $TestClass = new QueryService();
        // $TestClass->SetIntegratedServices($MockService);

        // Test DoQuery
        $QueryString = 'Some String since we did not specify it to the Mock';  // Could be checked with the Mock functions
        $this->assertEquals('One', $TestClass->DoQuery($QueryString));
    }
}
于 2013-08-28T14:19:07.877 に答える
0

PHPUnitSubject Under Test を作成するには、 を使用する必要があります。PHPUnitモックしたいメソッドを指定すると、これらのメソッドのみがモックされ、残りのクラス メソッドは元のクラスのままになります。

したがって、テストの例は次のようになります。

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));
}

とにかく、上記の答えが言うように、Dependency Injectionモックを可能にするためにパターンも使用IntegratedServiceする必要があります(上記の例に基づいて$result->success値を知る必要があるため)。

したがって、正しいテストは次のようになります。

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');
}
于 2013-08-29T07:49:02.830 に答える