2012-06-07 29 views
8

Tôi đang viết một bài kiểm tra PHPUnit, nơi tôi cần phải thử một số phụ thuộc, nhưng tôi cần một vài phương pháp cho nó vẫn hoạt động như trước đây. Ví dụ, tôi có:PHPUnit: giả lập tất cả các phương thức ngoại trừ một số

class Dependency { 
// some stuff not important for the test 
    public function thisOneINeed() { 
    /// complex code 
    } 
// some more stuff 
} 

Vì vậy, tôi đang làm một cái gì đó như thế này:

// prepare mock object 
$dep = $this->getMockBuilder('Dependency')->disableOriginalConstructor()->getMock(); 
// mock out some other method that should return fixed value 
$dep->expects($this->any())->method("shouldGetTrue")->will($this->returnValue(true)); 
// run test code, it will use thisOneINeed() and shouldGetTrue() 
$result = $testSubject->runSomeCode($dep); 
$this->assertEquals($expected, $result); 

Và mọi thứ đều tốt, ngoại trừ phương pháp thisOneINeed() đang chế giễu ra vì vậy tôi không nhận được mã phức tạp để chạy và tôi cần nó để chạy cho runSomeCode() để hoạt động bình thường. Mã đó trong thisOneINeed() không gọi bất kỳ phương thức nào khác, nhưng nó là cần thiết cho thử nghiệm thích hợp và nó không trả về giá trị cố định, vì vậy tôi không thể chỉ đặt returnValue tĩnh() ở đó. Và AFAIK PHPunit không có phương thức như returnValue() cho biết "gọi cho cha mẹ". Nó có returnCallback() nhưng không có cách nào để nói với nó "gọi phương thức này cho lớp cha" theo như tôi thấy.

Tôi có thể tạo danh sách tất cả các phương thức trong Dependency, xóa thisOneINeed khỏi nó và chuyển nó tới setMethods() khi tạo mô hình, nhưng tôi không thích cách tiếp cận đó, trông kludgy.

tôi cũng có thể làm điều này:

class MockDependency extends Dependency 
{ 
    // do not let the mock kill thisOneINeed function 
    final public function thisOneINeed() 
    { 
     return parent::thisOneINeed(); 
    } 
} 

và sau đó sử dụng MockDependency để xây dựng các đối tượng giả, và các công trình này quá, nhưng tôi không thích phải làm giả bằng tay.

Vì vậy, có cách nào tốt hơn để thực hiện việc này?

Trả lời

9

Tôi nghĩ nếu bạn muốn sử dụng trình tạo giả lập của PHPUnit, sau đó tạo một mảng của tất cả các phương thức, loại bỏ một phương thức bạn cần và chuyển nó đến setMethods chính xác là những gì bạn cần làm.

Cá nhân tôi thấy nó hữu ích trong nhiều trường hợp để có một lớp con của ReflectionClass mà tôi có thể thêm các phương thức vào khi tôi cần chúng.

class MyReflectionClass extends ReflectionClass 
{ 
    public function getAllMethodNamesExcept(array $excluded) 
    { 
     $methods = array_diff(
      get_class_methods($this->name), 
      $excluded 
     ); 
     return $methods; 
    } 
} 

Bạn cũng có thể sử dụng một khuôn khổ giả mạo khác có hỗ trợ những gì bạn muốn làm. Ví dụ: Phake có phương thức thenCallParent. Tôi đã bắt đầu sử dụng Phake gần đây bởi vì tôi cần thiết để có thể nắm bắt các tham số đã được chuyển cho một phương thức. Nó là tài liệu và đáng thử.

Các vấn đề liên quan