2013-01-04 21 views
5

Sử dụng PHPUnit và đối tượng giả, tôi đang thử kiểm tra một số mã sử dụng get_class để xác định xem đối tượng có được bộ lọc bao gồm hay không.Mã thử sử dụng get_class với đối tượng giả lập PHPUnit

Đây là lớp học để được kiểm tra:

class BlockFilter implements FilterInterface 
{ 
    private $classes; 

    public function __construct(array $classes = array()) 
    { 
     $this->classes = $classes; 
    } 

    public function isIncluded(NodeTraversableInterface $node) 
    { 
     if (Type::BLOCK != $node->getDocumentType()) { 
      return false; 
     } 

     if (! empty($this->classes)) { 
      /*** HERE IS THE PROBLEM: ***/ 
      return in_array(get_class($node), $this->classes); 
     } 

     return true; 
    } 
} 

Dưới đây là phương pháp từ bài kiểm tra đơn vị của tôi:

public function testIfContainerBlockIsIncluded() 
{ 
    $containerBlock = $this->getMock('Pwn\ContentBundle\Document\ContainerBlock'); 
    $containerBlock->expects($this->any())->method('getDocumentType')->will($this->returnValue(Type::BLOCK)); 

    $filter = new BlockFilter(array('Pwn\ContentBundle\Document\ContainerBlock')); 
    $this->assertTrue($filter->isIncluded($containerBlock)); 
} 

Đối tượng giả $containerBlock cư xử giống như các đối tượng thực Pwn\ContentBundle\Document\ContainerBlock; thậm chí mã sử dụng instanceof hoạt động (vì PHPUnit biến nó thành lớp con của lớp thực, tôi tin).

Mã đang được thử nghiệm sử dụng get_class để nhận giá trị chuỗi của lớp và so sánh nó với một mảng tên lớp dự kiến. Thật không may, đối với đối tượng giả, get_class trả về một cái gì đó như thế này:

Mock_ContainerBlock_ac231064 

(hậu tố _ac231064 thay đổi trên mỗi lời gọi).

Điều này làm cho thử nghiệm của tôi không thành công, vì vậy các tùy chọn của tôi là gì?

  • Làm lại mã để tránh sử dụng get_class? Điều này ngụ ý get_class không nên được sử dụng khi cố gắng viết mã có thể kiểm thử.
  • Sử dụng một thể hiện thực sự của lớp ContainerBlock thay vì một mô hình? Điều này có nghĩa là chúng tôi đang thử nghiệm hiệu quả cả hai lớp học cùng một lúc.
  • Một số thủ thuật khôn ngoan khác mà tất cả các bạn sẽ đề xuất ??? ;)

Nhờ sự giúp đỡ ...

Trả lời

2

Vượt qua tên lớp của Mock trong các thử nghiệm:

new BlockFilter(array(get_class($this->containerBlock))); 
+0

Ý tưởng tốt, tôi nghĩ rằng đây là ở phía sau tâm trí của tôi thực sự nhưng nó dường như làm cho thử nghiệm bằng cách nào đó 'nhân tạo'; Tôi sẽ ít có khả năng phát hiện ra một sai lầm với bản thân bài kiểm tra. Vì vậy, bây giờ tôi tự hỏi nếu điều này là tốt hơn hoặc tồi tệ hơn bằng cách sử dụng các đối tượng thực sự thay vì mocks ... – fazy

+0

@LarsJ Tôi không thấy bất kỳ vấn đề với điều đó. BlockFilter của bạn đang thử nghiệm các tên lớp trong mảng, vì vậy việc truyền tên lớp của Mock là hoàn toàn ổn. Trên một sidenote, tôi sẽ thử giao diện thay vì ContainerBlock, vì đó là những gì TypeHint on isIncluded yêu cầu. – Gordon

+1

Cảm ơn bạn một lần nữa vì tất cả những suy nghĩ và bình luận của bạn; Tôi đã đưa nó vào thực tế và nó hoạt động tốt. – fazy

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