2010-06-29 4 views
33

PHPUnit으로 PDO 객체를 조롱하는 데 어려움이 있습니다.PHPUnit을 사용하여 PDO 객체를 조롱

내 문제에 대한 웹 그러나 나는 무엇을 수집 할 수 있습니다에서 많은 정보가있을 것 같지 않습니다

  1. PDO는 '마지막'__wakeup 및 직렬화되지 않도록 __sleep 방법이있다.
  2. PHPunit의 mock 객체 구현은 어느 시점에서 객체를 직렬화합니다.
  3. 그런 다음 단위 테스트는 PDO에서 발생하는 PHP 오류로 실패합니다.

    class MyTest extends PHPUnit_Framework_TestCase 
    
    {  
        protected $backupGlobals = FALSE; 
        // ... 
    
    } 
    

    출처 : http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html

    나를 위해 작업이 밤은, 내 테스트는 여전히 생산이 문제를 방지하는 의미 기능이 당신의 단위 테스트에 다음 줄을 추가하여이

오류.

전체 테스트 코드 :

class MyTest extends PHPUnit_Framework_TestCase 
{ 

    /** 
    * @var MyTest 
    */ 
    private $MyTestr; 

    protected $backupGlobals = FALSE; 

    /** 
    * Prepares the environment before running a test. 
    */ 
    protected function setUp() 
    { 
     parent::setUp(); 

    } 

    /** 
    * Cleans up the environment after running a test. 
    */ 
    protected function tearDown() 
    { 

     parent::tearDown(); 
    } 

    public function __construct() 
    { 

     $this->backupGlobals = false; 
     parent::__construct(); 

    } 


    /** 
    * Tests MyTest->__construct() 
    */ 
    public function test__construct() 
    { 

     $pdoMock = $this->getMock('PDO', array('prepare'), array(), '', false); 

     $classToTest = new MyTest($pdoMock); 

     // Assert stuff here! 


    } 

    // More test code....... 

없음 phpunit을이의 나에게 손을주는 프로?

감사합니다,

답변

47

$ backupGlobals 당신을 도움이되지 않습니다 :) 아마도 잘못된 것입니다. 원래 생성자를 실행하지 getMock을 요청하는 경우 때 unserialize를 사용하여 phpunit을 3.5.2 (아마도 이전 버전뿐만 아니라이) phpunit을/프레임 워크에 다음 코드를 가지고/모의 객체는/Generator.php

if ($callOriginalConstructor && 
     !interface_exists($originalClassName, $callAutoload)) { 
     if (count($arguments) == 0) { 
      $mockObject = new $mock['mockClassName']; 
     } else { 
      $mockClass = new ReflectionClass($mock['mockClassName']); 
      $mockObject = $mockClass->newInstanceArgs($arguments); 
     } 
    } else { 
     // Use a trick to create a new object of a class 
     // without invoking its constructor. 
     $mockObject = unserialize(
      sprintf(
      'O:%d:"%s":0:{}', 
      strlen($mock['mockClassName']), $mock['mockClassName'] 
     ) 
     ); 
    } 

이 "속임수" PDO와 함께 즉시 실패 할 것입니다.

그래서 어떻게 해결할 수 있습니까?

하나의 옵션은 여기에 목표는 당신이 필요하지 않은 원래의 PDO 생성자를 제거하는 것입니다이

class mockPDO extends PDO 
{ 
    public function __construct() 
    {} 

} 

같은 테스트 도우미를 만드는 것입니다. 원래의 생성자를 실행이 같은 모의 만들기

$pdoMock = $this->getMock('mockPDO', array('prepare')); 

하지만 지금 mockPDO 테스트 도우미에 무해 덕분이기 때문에, 당신은 테스트를 계속 할 수 있습니다 다음, 여기에 테스트 코드를 변경합니다.

+0

이 작업을 수행합니다. 감사! – uckelman

+1

당신은 아빠입니다! 대단히 감사합니다. 나는이 문제를 해결하기 위해 포기했다! –

+0

나는 원래의 포스터와 같은 문제가있어서 당신의 솔루션을 사용했다. 그러나 이제는 내 타입 힌팅이 더 이상 PDO로 보지 않습니다. 'PDO의 인스턴스 여야합니다, 주어진 Mock_PDOMock_96936f72 인스턴스' – nvanesch

2

내가 runkit를 사용하고 runkit_function_redefine을 사용하여 보호로 마지막 두 방법을 재정의하는 것입니다 생각할 수있는 최선.

php.ini에서 runkit.internal_override 설정을 활성화하려면 비활성화하십시오. runkit 대답처럼 보인다 경우이 오류가 다른 곳에서 오기 때문에

그리고는 이제까지 평가와 마찬가지로, 문제는,

+0

테스트 목적으로'runkit' 또는'eval'을 사용하면 문제가 있다고 생각하지 않습니다. – netcoder

1

테스트 사례를 인스턴스화하고 있습니까?

$classToTest = new MyTest($pdoMock); 

바로 지금 테스트 케이스를 테스트하고 있습니다. 그것은 다음과 같은 것이어야합니다 :

$classToTest = new My($pdoMock); 
+0

그건 원래 질문의 버그입니다. – uckelman

관련 문제