0

我想对 zend 框架 3 教程页面上的专辑应用程序实现进行单元测试。我在原始实现中添加了一些功能(登录和 acl)。我按照教程进行单元测试 zf3,但无法遵循它,如何模拟身份验证和编写更多测试用例。感谢任何帮助。一些代码来自我的相册应用程序实现。

zf3 的单元测试教程

专辑控制器.php

<?php
namespace Album\Controller;

use Album\Model\AlbumTable;
use Album\Model\LoginTable;
use Album\Controller\LoginController;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Album\Form\AlbumForm;
use Album\Model\Album;
use Zend\Paginator\Adapter\Iterator as paginatorIterator;
use Zend\Paginator\Paginator;
use Zend\Db\Sql\Select;
use Album\Form\SearchForm;
use Zend\Session\Container;
use Album\Utility\Acl;
use \Zend\Mvc\MvcEvent;

class AlbumController extends AbstractActionController
{
  private $table;
  protected $role;
  public function __construct(AlbumTable $table){
     $this->table = $table;
 } 

 public function onDispatch(MvcEvent $e)
 {
   $userSession = new Container('user');
   if (!isset($userSession->email)) {
    return $this->redirect()->toRoute('login');
 }else {
    $this->role = $userSession->role;
    parent::onDispatch($e);
 }
}
 public function authorize($role,$action)
{
   if($role == 'admin'){
     $acl = new Acl();
     if ($acl->isAllowed('admin', 'AlbumController', $action)) {
       return true;
    }
 }
  return false;
}

 public function indexAction(){
    $searchform = new SearchForm();
    $searchform->get('submit')->setValue('search');
    $select = new Select();
    $order_by = $this->params()->fromRoute('order_by') ?$this->params()->fromRoute('order_by') : 'id';
    $search="";
    $order = $this->params()->fromRoute('order') ?$this->params()->fromRoute('order') : Select::ORDER_ASCENDING;
    $page = $this->params()->fromRoute('page') ? (int) $this->params()->fromRoute('page') : 1;
    $request = $this->getRequest();
    if ($request->isGet())
    {
      $formdata    = (array) $request->getQuery();
      $search_data = array();
      foreach ($formdata as $key => $value)
      {
        if ($key != 'submit')
       {
         if (!empty($value))
         {
          $search_data[$key] = $value;
        }
      }
    }
    if (!empty($search_data))
    {
      $search = $search_data;
    }
    $searchform->setData($formdata);
  }
  $search_by = $this->params()->fromQuery() ? $this->params()->fromQuery() : '';
  $paginator = $this->table->fetchAll($order_by,$order,$search,$select);
        $page = (int) $this->params()->fromQuery('page', 1);
        $page = ($page < 1) ? 1 : $page;
        $paginator->setCurrentPageNumber($page);
        $paginator->setItemCountPerPage(10);
        return new ViewModel([
    'search_by'=> $search_by,
    'order_by' => $order_by,
    'order' => $order,
    'page' => $page,
    'paginator' => $paginator,
    'pageAction' => 'album',
    'form'       => $searchform,
    'flashMessages' => $this->flashMessenger()->getMessages(),
    ]);
}
 public function addAction()
{
  $action = 'add';
  $permission = $this->authorize($this->role,$action);
  if (!$permission) {
     $this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>You dont have the privilege to add!!</b></div>');
    return $this->redirect()->toRoute('album');
}

$form = new AlbumForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();

if ($request->isPost()) {
  $album = new Album();
  $form->setInputFilter($album->getInputFilter());
  $form->setData($request->getPost());
  $add = $request->getPost('submit', 'Cancel');

  if($add == 'Cancel'){
    $this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>Cancelled by User...!!</b></div>');
    return $this->redirect()->toRoute('album');
  }

  if ($form->isValid()) {
    $album->exchangeArray($form->getData());
    $this->table->saveAlbum($album);
    $this->flashMessenger()->addMessage('<div class="alert alert-success" role="alert"><b>Added Successfully...</b></div>');
  }else {
    $this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>Failed to Add...!!</b></div>');
    return array('form' => $form);
  }
  return $this->redirect()->toRoute('album');
}
return array('form' => $form);
}

 public function editAction()
{
  $action = 'edit';
  $permission = $this->authorize($this->role,$action);
  if (!$permission) {
    $this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>You dont have the privilege to edit!!</b></div>');
    return $this->redirect()->toRoute('album');
}
$id = (int) $this->params()->fromRoute('id', 0);

if (0 === $id) {
  return $this->redirect()->toRoute('album', ['action' => 'add']);
}
try {
  $album = $this->table->getAlbum($id);
}catch (\Exception $e) {
  return $this->redirect()->toRoute('album', ['action' => 'index']);
}

$form = new AlbumForm();
$form->bind($album);
$form->get('submit')->setAttribute('value', 'Edit');

$request = $this->getRequest();
$viewData = ['id' => $id, 'form' => $form];

if (! $request->isPost()) {
  return $viewData;
}

$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
$edit = $request->getPost('submit', 'Cancel');

if($edit == 'Cancel'){
  $this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>Cancelled by User...!!</b></div>');
  return $this->redirect()->toRoute('album');
}

if (! $form->isValid()) {
  $this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>Failed to Update...!!</b></div>');
  return $viewData;
}else{
  $this->table->saveAlbum($album);
  $this->flashMessenger()->addMessage('<div class="alert alert-success" role="alert"><b>Record Updated Successfully...!!</b></div>');
}
return $this->redirect()->toRoute('album', ['action' => 'index']);
}

public function deleteAction()
{
 $action = 'delete';
$permission = $this->authorize($this->role,$action);
if (!$permission) {
  $this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>You dont have the privilege to delete!!</b></div>');
  return $this->redirect()->toRoute('album');
}

$id = (int) $this->params()->fromRoute('id', 0);
if (!$id) {
 return $this->redirect()->toRoute('album');
}
$request = $this->getRequest();
if ($request->isPost()) {
 $del = $request->getPost('del', 'No');
if ($del == 'Yes') {
  $id = (int) $request->getPost('id');
  $this->table->deleteAlbum($id);
  $this->flashMessenger()->addMessage('<div class="alert alert-success" role="alert"><b>Record Deleted Successfully...!!</b></div>');
 }else{
  $this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>Failed to delete...!!</b></div>');
}
 return $this->redirect()->toRoute('album');
}
return [
  'id'    => $id,
  'album' => $this->table->getAlbum($id),
 ];
 }
}

登录控制器.php

<?php

namespace Album\Controller;

use Album\Form\LoginForm;
use Album\Model\Login;
use Album\Model\LoginTable;
use Zend\Authentication\Adapter\DbTable as AuthAdapter;
use Zend\Authentication\AuthenticationService;
use Zend\Authentication\Result;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Session\Container;
use Zend\Db\Adapter\Adapter as DbAdapter;

class LoginController extends AbstractActionController
{
    public $userSession;
    public $loginTable;
    public function __construct(LoginTable $loginTable)
    {
      $this->loginTable = $loginTable;
    }
 public function loginAction()
 {
    $userSession = new Container('user');
    if(!isset($userSession->email)){
    $form = new LoginForm();
    $form->get('submit')->setValue('Login');

    $request = $this->getRequest();

     if ($request->isPost()){
       $login = new Login();
       $form->setInputFilter($login->getInputFilter());
       $form->setData($request->getPost());
       if ($form->isValid())
       {
         $data=$form->getData();
         $dbAdapter = new DbAdapter(array(
           'driver'         => 'Pdo',
           'dsn'            => 'mysql:dbname=customers;host=localhost;',
           'username' => "root",
           'password' => "",
         ));

            $authAdapter=new AuthAdapter($dbAdapter,'login','email','password');
                  $authAdapter->setTableName('login')->setIdentityColumn('email')->setCredentialColumn('password');
                  $authAdapter->setIdentity($data['email'])->setCredential($data['password']);
            $auth=new AuthenticationService();
            $result = $auth->authenticate($authAdapter);
            switch ($result->getCode())
                        {
                  case Result::FAILURE_IDENTITY_NOT_FOUND:
                    break;
                  case Result::FAILURE_CREDENTIAL_INVALID:
                                break;
                  case Result::SUCCESS:
                    $userSession->email = $data['email'];
                    $row=$this->loginTable->getRow($userSession->email);
                    $userSession->role = $row['role'];
                    $this->flashMessenger()->addMessage('<div class="alert alert-success" role="alert"><b>Login Successful!!</b></div>');
                                return $this->redirect()->toRoute('album', array('action' => 'index'));
                  default :
                    return $this->redirect()->toRoute('home');
                    break;
            }
         }
     }
     return array('form' => $form,'fm' => $this->flashMessenger()->getMessages(),);
    }
    return $this->redirect()->toRoute('album');
}

public function logoutAction(){
    $session = new Container('User');
    $session->getManager()->destroy();
    $auth=new AuthenticationService();
      $auth->clearIdentity();
    return $this->redirect()->toRoute('login');
 }
}
4

1 回答 1

1

ZF 有一个服务管理器,可用于依赖注入。您已经在使用它,因为您将 UserTable 和 LoginTable 注入到控制器中。将对象注入控制器和其他服务的主要原因是可重用性和可测试性。这两个注入的服务可以很容易地被模拟,并且模拟的版本可以在测试期间被注入到这些类中。

您在控制器内部或其操作中实例化的所有对象都不能被模拟。所以你想重构并取出ACL、用户会话容器和AuthenticationService。如果需要,为那些编写工厂并将它们添加到服务管理器中。最后在需要的地方将它们注入控制器。现在您可以模拟它们或为每个组件编写单独的测试。

下一个问题是在控制器内部构建查询以创建数据库连接。同样,创建数据库连接将进入工厂,因此您可以重用它并在需要的地方注入它。构建查询将进入存储库。Als 用户名和密码应该进入一个本地配置文件(一个被 git 忽略的文件)。

ZendFramework 有多个包可以帮助您:

于 2016-11-08T07:06:27.043 回答