2013-02-10 20 views
23

Tôi đã tìm hiểu về kiểm tra đơn vị và tôi đã cố gắng để giải quyết vấn đề sau:ZF2 authentication đơn vị thử nghiệm

Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for zfcUserAuthentication 

... bằng cách sử dụng câu trả lời duy nhất cho tại địa chỉ:

Simple ZF2 Unit Tests for a controller using ZfcUser

Vì vậy, chức năng thiết lập của tôi trông giống nhau. Thật không may, tôi nhận được thông báo lỗi:

Zend\Mvc\Exception\InvalidPluginException: Plugin of type Mock_ZfcUserAuthentication_868bf824 is invalid; must implement Zend\Mvc\Controller\Plugin\PluginInterface 

Nó được gây ra tại khu vực này của mã (chia tay trong mã của tôi theo cách tương tự):

$this -> controller->getPluginManager() 
->setService('zfcUserAuthentication', $authMock); // Error refers to this line. 

Các $ authMock đối tượng là rõ ràng không triển khai thực hiện plugininterface, mà tôi cần thực hiện để chuyển sang setService.

Có phải $ authMock không có nghĩa là được chuyển đến đó để sử dụng trong thử nghiệm đơn vị không? Tôi có nên sử dụng phương pháp setService khác (đơn vị thử nghiệm theo định hướng) không?

Tôi cần một cách để xử lý đăng nhập vào ứng dụng của mình hoặc thử nghiệm đơn vị của tôi là vô nghĩa.

Cảm ơn lời khuyên nào.

=== Sửa (2013/11/02) ===

tôi muốn tập trung vào phần này để làm rõ, như tôi nghĩ rằng đây là khu vực có vấn đề:

// Getting mock of authentication object, which is used as a plugin. 
$authMock = $this->getMock('ZfcUser\Controller\Plugin\ZfcUserAuthentication'); 

// Some expectations of the authentication service. 
$authMock -> expects($this->any()) 
    -> method('hasIdentity') 
    -> will($this->returnValue(true)); 

$authMock -> expects($this->any()) 
    -> method('getIdentity') 
    -> will($this->returnValue($ZfcUserMock)); 

// At this point, PluginManager disallows mock being assigned as plugin because 
// it will not implement plugin interface, as mentioned. 
$this -> controller->getPluginManager() 
->setService('zfcUserAuthentication', $authMock); 

Nếu giả lập không xử lý các triển khai cần thiết, làm cách nào khác để tôi giả vờ đăng nhập?

+0

Tôi có đúng không khi cần kiểm tra đơn vị vì đây là mô hình? Tôi thấy đó là nơi tôi giữ tất cả mã xác thực của mình. – Shoreline

+0

Tôi đã làm một cái gì đó tương tự gần đây mà không có vấn đề gì. Lớp học testcase hoàn chỉnh của bạn trông như thế nào? Ngoài ra bootstrap thử nghiệm của bạn trông như thế nào? Và cuối cùng là hành động mà bạn đang cố gắng thử nghiệm. – Ruben

+0

Bạn có sử dụng cấu hình ứng dụng đặc biệt khi kiểm tra đơn vị không? Có thể trong trường hợp đó mô-đun zfcUser không được nạp trong môi trường thử nghiệm. – SmasherHell

Trả lời

3

Bạn gặp sự cố với khoảng cách tên hoặc trình tải tự động của mình.

Khi bạn tạo mô hình, định nghĩa lớp học của ZfcUser\Controller\Plugin\ZfcUserAuthentication không được tìm thấy. Vì vậy, PHPUnit tạo ra một mô hình chỉ mở rộng lớp này cho thử nghiệm của bạn. Nếu lớp đã có sẵn thì PHPUnit sẽ sử dụng lớp thực tế để mở rộng khi tạo mô hình của nó, sau đó sẽ sử dụng các lớp/giao diện cha mẹ.

Bạn có thể thấy logic này ở đây: https://github.com/sebastianbergmann/phpunit-mock-objects/blob/master/PHPUnit/Framework/MockObject/Generator.php

if (!class_exists($mockClassName['fullClassName'], $callAutoload) && 
     !interface_exists($mockClassName['fullClassName'], $callAutoload)) { 
     $prologue = 'class ' . $mockClassName['originalClassName'] . "\n{\n}\n\n"; 

     if (!empty($mockClassName['namespaceName'])) { 
      $prologue = 'namespace ' . $mockClassName['namespaceName'] . 
         " {\n\n" . $prologue . "}\n\n" . 
         "namespace {\n\n"; 

      $epilogue = "\n\n}"; 
     } 

     $cloneTemplate = new Text_Template(
      $templateDir . 'mocked_clone.tpl' 
     ); 

Vì vậy, nếu không có lớp học hoặc giao diện, PHPUnit sẽ thực sự tạo ra một bản thân để các mô hình sẽ đáp ứng các loại gián tiếp của tên lớp gốc. Tuy nhiên, bất kỳ lớp cha mẹ hoặc giao diện nào sẽ không được đưa vào bởi vì PHPUnit không nhận thức được chúng.

Điều này sẽ do không bao gồm không gian tên thích hợp trong thử nghiệm của bạn hoặc gặp sự cố trong trình tải tự động của bạn. Thật khó để nói mà không thực sự nhìn thấy toàn bộ tập tin thử nghiệm.


Ngoài ra chứ không phải chế giễu ZfcUser\Controller\Plugin\ZfcUserAuthentication, bạn có thể thử các Zend\Mvc\Controller\Plugin\PluginInterface trong thử nghiệm của bạn và vượt qua đó vào quản lý plugin. Mặc dù nếu bạn là loại gợi ý cho plugin trong mã của bạn, kiểm tra của bạn vẫn không hoạt động.

//Mock the plugin interface for checking authorization 
$authMock = $this->getMock('Zend\Mvc\Controller\Plugin\PluginInterface'); 

// Some expectations of the authentication service. 
$authMock -> expects($this->any()) 
    -> method('hasIdentity') 
    -> will($this->returnValue(true)); 

$authMock -> expects($this->any()) 
    -> method('getIdentity') 
    -> will($this->returnValue($ZfcUserMock)); 

$this -> controller->getPluginManager() 
->setService('zfcUserAuthentication', $authMock); 
0

Tôi vừa tạo ví dụ cho plugin FlashMessenger. Bạn chỉ nên sử dụng ControllerPluginManager để ghi đè lên ControllerPlugin. Đảm bảo rằng trình khởi động ứng dụng của bạn gọi setApplicationConfig();

<?php 
namespace SimpleTest\Controller; 

use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase; 

class SimpleControllerTest extends AbstractHttpControllerTestCase { 

    public function testControllerWillAddErrorMessageToFlashMessenger() 
    { 
     $flashMessengerMock = $this->getMockBuilder('\Zend\Mvc\Controller\Plugin\FlashMessenger', array('addErrorMessage'))->getMock(); 
     $flashMessengerMock->expects($this->once()) 
      ->method('addErrorMessage') 
      ->will($this->returnValue(array())); 


     $serviceManager = $this->getApplicationServiceLocator(); 
     $serviceManager->setAllowOverride(true); 
     $serviceManager->get('ControllerPluginManager')->setService('flashMessenger', $flashMessengerMock); 

     $this->dispatch('/error/message'); 

    } 
}?>