2012-02-28 26 views
13

Trong phpunit chúng ta có thể xác định phương pháp này được gọi với biệtKiểm tra xem phương pháp mô hình được gọi là không có bất kỳ thông số thông qua (trong phpunit)

->with($this->equalTo('foobar')) 

hoặc bất kỳ

->with($this->anything()) 

tham số.

Nhưng có cách nào để xác định rằng phương thức đã được gọi mà không có tham số nào cả?

Đây là thử nghiệm Tôi hy vọng đến thất bại:

public function testZ() 
{ 
    $a = $this->getMock('q'); 

    $a->expects($this->once()) 
     ->method('z') 
     ->with(); // <--- what constraint to specify here? 

    $a->z(1); 
} 

UPD:

Câu hỏi đặt ra có tính chất lý thuyết, vì vậy tôi không có bất kỳ ví dụ thực tế đời sống. Một số trường hợp nó có thể hữu ích tôi có thể nghĩ ngay bây giờ là:

public function testMe($object) 
{ 
    $object->foo(); 
} 

Và chúng ta hãy giả sử rằng testMe nên (do thiết kế và do yêu cầu) luôn gọi phương thức không có tham số (giả sử foo() có những mặc định). Bởi vì bất kỳ tham số không mặc định (chính xác hơn: bất kỳ tham số nào! = Mặc định, mà chúng ta chưa biết và có thể thay đổi một cách độc lập) trong trường hợp này gây hậu quả chết người.

+0

+1 Tôi đã dành một vài phút xem qua nguồn PHPUnit trên github và có vẻ như '-> với()' chỉ hoạt động để xác định các tham số, không cấm chúng. Tôi không thể thực sự nghĩ về một kịch bản mà xác minh rằng không có đối số được thông qua là cái gì bạn cần phải kiểm tra, mặc dù? Tôi muốn được quan tâm để nghe lý do tại sao bạn cần phải xác minh rằng không có đối số đã được gửi. Vượt qua một đối số khi không ai dự kiến ​​sẽ không phá vỡ bất cứ điều gì và bạn có thể không vượt qua trong một NULL khi có một đối số dự kiến ​​rằng không thể được cung cấp? – rdlowrey

+0

@rdlowrey: thêm bản cập nhật giải thích ;-) – zerkms

+0

@rdlowrey: 'bạn không thể bỏ qua NULL khi có đối số dự kiến ​​không thể cung cấp' --- không bạn không thể. Phương pháp vẫn có thể có các tham số tùy chọn – zerkms

Trả lời

6

Trong khi rdlowrey đúng là with() không đưa ra các điều khoản để kiểm tra không có đối số nào được chuyển, vấn đề không nằm trong PHPUnit mà là chính PHP.

Trước tiên, nếu phương pháp của bạn không cung cấp giá trị mặc định, trình thông dịch sẽ gây ra lỗi nghiêm trọng nếu bạn không chuyển bất kỳ thông số nào. Điều này được mong đợi và không hoàn toàn liên quan đến câu hỏi trong tầm tay, nhưng điều quan trọng là phải nêu lên phía trước.

Thứ hai, nếu phương pháp của bạn cung cấp giá trị mặc định, gọi phương thức không có đối số sẽ khiến PHP thay đổi cuộc gọi trước khi PHPUnit tham gia để vượt qua giá trị mặc định. Đây là một thử nghiệm đơn giản cho thấy PHP chèn chính nó trước khi PHP có thể kiểm tra các tham số. Đó là chìa khóa để nhận ra rằng lớp mô hình mà PHP tạo ra có cùng chữ ký với lớp được mô phỏng - bao gồm cả các giá trị mặc định.

class MockTest extends PHPUnit_Framework_TestCase { 
     public function test() { 
       $mock = $this->getMock('Foo', array('bar')); 
       $mock->expects($this->once()) 
        ->method('bar') 
        ->with() // does nothing, but it doesn't matter 
        ->will($this->returnArgument(0)); 
       self::assertEquals('foobar', $mock->bar()); // PHP inserts 1 and 2 
       // assertion fails because 1 != 'foobar' 
     } 
} 

class Foo { 
     public function bar($x = 1, $y = 2) { 
       return $x + $y; 
     } 
} 

Điều này có nghĩa bạn có thể xác minh rằng hoặc gì đã được thông qua hoặc các giá trị mặc định đã được thông qua, nhưng bạn không thể cụ thể hơn.

Bạn có thể vượt qua giới hạn này không? Bạn có thể xóa các giá trị mặc định khỏi các đối số khi ghi đè các phương thức, vì vậy bạn có thể tạo một lớp con và giả lập nó. Nó có đáng không? Phản ứng ruột đầu tiên của tôi là đây là một mùi mã rất lớn. Hoặc là thiết kế của bạn hoặc thử nghiệm của bạn đang làm điều sai (tm).

Nếu bạn có thể cung cấp một ví dụ cụ thể trong thế giới thực, nơi bạn thực sự cần thực hiện loại thử nghiệm này, bạn nên dành thời gian cân nhắc giải pháp. Cho đến lúc đó, tôi hài lòng với câu trả lời hoàn toàn về học thuật "không làm điều đó". :)

+0

+1 để làm rõ. Tôi đồng ý rằng nó có vẻ như một mùi mã ... Tôi đã không nhìn thấy một ứng dụng thực tế cho nó và nó có vẻ như một vấn đề mà một refactoring đơn giản sẽ tránh. – rdlowrey

+0

"Cho đến lúc đó, tôi hài lòng với câu trả lời hoàn toàn về học thuật" không làm điều đó ". :)" --- Tôi đồng ý rằng tôi không thể nghĩ ra ví dụ thế giới thực và đó là lý do tại sao tôi nói "Câu hỏi có tính chất lý thuyết "- vì vậy tôi chỉ hỏi về khả năng lý thuyết để làm điều đó mà không có giải thích tại sao tôi cần điều đó ;-) – zerkms

+0

Nhưng vẫn tự hỏi làm thế nào chế nhạo không – zerkms

4

Đối tượng giả lập PHPUnit chỉ có thể sử dụng phương pháp ràng buộc ->with() để xác minh rằng số lượng hoặc giá trị tương ứng của thông số đã truyền khớp với thông số được chuyển đến phương thức giả khi được gọi. Bạn không thể sử dụng nó để yêu cầu rằng không có đối số được chuyển đến phương thức giả.

Quy trình xác minh mô phỏng đặc biệt kiểm tra số lượng thông số đã chuyển và giá trị được liên kết tương thích với các thông số được chuyển đến ràng buộc with. Ngoài ra, như bạn có thể thấy, xác định ràng buộc with mà không có bất kỳ giá trị nào cũng sẽ không hoạt động; nếu with không nhận được thông số, nó sẽ không thêm bất kỳ ràng buộc tham số nào để xác minh.

Bạn có thể thấy phương thức PHPUnit_Framework_MockObject_Matcher_Parameters::verify thực tế được sử dụng để xác minh thông số phương pháp giả trong nguồn github được liên kết.

Nếu xác thực không có đối số đã qua là yêu cầu bạn cần phải chỉ định lớp mô hình của riêng bạn để xác minh điều kiện bên ngoài khả năng giả lập PHPUnit.

+0

Nếu không chỉnh sửa câu trả lời này, tôi muốn nói thêm rằng tôi đã đi đến kết luận này không phải từ sự hiểu biết sâu sắc về mặt nội bộ của PHPUnit, mà từ một thời gian dài tìm kiếm mã nguồn có liên quan trong nỗ lực thực hiện mục tiêu đã nêu của câu hỏi. Tôi tin rằng mã nguồn được liên kết là bằng chứng cho thấy điều đó là không thể, nhưng nếu ai đó có thể tìm ra cách để làm cho nó hoạt động, hãy chia sẻ. – rdlowrey

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