2008-11-10 34 views
75

Cách để tránh phpunit phải gọi hàm tạo cho đối tượng giả? Nếu không, tôi sẽ cần một đối tượng giả như đối số constructor, một số khác cho rằng vv Các api có vẻ như thế này:phpunit tránh đối số hàm tạo cho mock

getMock($className, $methods = array(), array $arguments = array(), 
     $mockClassName = '', $callOriginalConstructor = TRUE, 
     $callOriginalClone = TRUE, $callAutoload = TRUE) 

Tôi không làm cho nó hoạt động. Nó vẫn phàn nàn về đối số hàm tạo, ngay cả với $callOriginalConstructor được đặt thành false.

Tôi chỉ có một đối tượng trong hàm tạo và nó là một sự tiêm phụ thuộc. Vì vậy, tôi không nghĩ rằng tôi có một vấn đề thiết kế ở đó.

Trả lời

1

Có lẽ bạn cần phải tạo một nhánh để truyền vào làm đối số hàm tạo. Sau đó, bạn có thể phá vỡ chuỗi các đối tượng giả.

+1

bạn có thể vui lòng chia sẻ thêm một số thông tin –

0

PHPUnit được thiết kế để gọi hàm tạo trên đối tượng giả; để tránh tình trạng này bạn nên một trong hai:

  1. Tiêm một đối tượng giả như một sự phụ thuộc vào đối tượng bạn gặp sự cố chế giễu
  2. Tạo một lớp thử nghiệm kéo dài lớp bạn đang cố gắng gọi đó là không gọi constructor mẹ
40

Ở đây bạn đi:

// Get a Mock Soap Client object to work with. 
    $classToMock = 'SoapClient'; 
    $methodsToMock = array('__getFunctions'); 
    $mockConstructorParams = array('fake wsdl url', array()); 
    $mockClassName = 'MyMockSoapClient'; 
    $callMockConstructor = false; 
    $mockSoapClient = $this->getMock($classToMock, 
            $methodsToMock, 
            $mockConstructorParams, 
            $mockClassName, 
            $callMockConstructor); 
+0

Điều này dường như gần như những gì tôi muốn. Tôi muốn gọi getMock với lớp duy nhất để được chế giễu và $ callMockConstructor. Làm sao? một cái gì đó như thế này: $ this-> getMock ($ classToMock, $ callMockConstructor). Điều duy nhất tôi có thể nghĩ đến là đi vào nguồn PHPUnit và thay đổi nó thành mặc định = false. – Gutzofter

+1

Tôi đã thay đổi mặc định thành false trong testcase.php. Bạn sẽ nghĩ rằng nó sẽ được đặt cho false theo mặc định. Mocking một constructor có vẻ rất kỳ lạ – Gutzofter

+0

OBTW, Cảm ơn bạn! – Gutzofter

121

bạn có thể sử dụng getMockBuilder thay vì chỉ getMock:

$mock = $this->getMockBuilder('class_name') 
    ->disableOriginalConstructor() 
    ->getMock(); 

Xem phần trên "Test Doubles" trong PHPUnit's documentation để biết chi tiết.

Mặc dù bạn có thể làm điều này, tốt hơn hết là không cần. Bạn có thể cấu trúc lại mã của bạn để thay vì một lớp cụ thể (với một hàm tạo) cần được tiêm, bạn chỉ phụ thuộc vào một giao diện. Điều này có nghĩa là bạn có thể giả lập hoặc stub giao diện mà không cần phải nói với PHPUnit để sửa đổi hành vi của hàm tạo.

+0

Điều này làm việc tuyệt vời cho tôi. Đó là ví dụ 10.3, mặc dù. Tôi đã cố gắng chỉnh sửa bài đăng nhưng SO đã khởi động lại để chỉnh sửa quá ngắn. – Matthew

+0

Cảm ơn @Lytithwyn. Đã cập nhật câu trả lời. – dave1010

+0

cũng làm việc cho tôi. Cảm ơn! – Jeune

3

Là phụ lục, tôi muốn đính kèm expects() cuộc gọi đến đối tượng được giả mạo của tôi và sau đó gọi hàm tạo. Trong PHPUnit 3.7.14, đối tượng được trả về khi bạn gọi disableOriginalConstructor() theo nghĩa đen là một đối tượng.

// Use a trick to create a new object of a class 
// without invoking its constructor. 
$object = unserialize(
sprintf('O:%d:"%s":0:{}', strlen($className), $className) 

Thật không may, trong PHP 5.4 có một tùy chọn mới mà họ không sử dụng:

ReflectionClass::newInstanceWithoutConstructor

Vì đây là không có, tôi đã tự phản ánh lớp và sau đó gọi nhà xây dựng.

$mock = $this->getMockBuilder('class_name') 
    ->disableOriginalConstructor() 
    ->getMock(); 

$mock->expect($this->once()) 
    ->method('functionCallFromConstructor') 
    ->with($this->equalTo('someValue')); 

$reflectedClass = new ReflectionClass('class_name'); 
$constructor = $reflectedClass->getConstructor(); 
$constructor->invoke($mock); 

Lưu ý, nếu functionCallFromConstructprotected, bạn đặc biệt phải sử dụng setMethods() để các phương pháp bảo vệ được chế giễu. Ví dụ:

$mock->setMethods(array('functionCallFromConstructor')); 

setMethods() phải được gọi trước cuộc gọi expect(). Cá nhân, tôi chuỗi này sau disableOriginalConstructor() nhưng trước getMock().

1

Hoặc bạn có thể thêm thông số vào getMock để ngăn việc gọi hàm khởi tạo mặc định.

$mock = $this->getMock(class_name, methods = array(), args = array(), 
     mockClassName = '', callOriginalConstructor = FALSE); 

Tuy nhiên, tôi nghĩ câu trả lời của dave1010 trông đẹp hơn, đây chỉ là vì mục đích hoàn chỉnh.

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