我如何在Symfony中为此编写测试?

时间:2012-11-20 15:29:52

标签: unit-testing symfony phpunit

我即将深入研究PHP世界中的测试,我有一些问题。我有一个处理贷款申请的控制器。然后,大部分工作被委托给ProcessLoanApplication类。

ApplyController

class ApplyController extends Controller
{
  public function indexAction(Request $request)
  {
    $form = $this->createForm(new LoanApplication());

    if($request->getMethod() == 'POST') {
        $form->bind($request);

        if($form->isValid()) {

            $session = $this->getRequest()->getSession();

            $loan_app_processor = new Tasks\ProcessLoanApplication($form, $session);
            $loan_app_processor->process();

            return $this->redirect($this->generateUrl('apply_thanks'));
        }
    }

任务\ ProcessLoanApplication

class ProcessLoanApplication
{
  private $_QuickBaseModels;
  private $_session;
  private $_app; // submitted form data
  private $_existingApp = false; // holds existing application in QB, if it exists

  public function __construct(Form $form, Session $session)
  {
    $this->_app = $form->getNormData();
    $this->_session = $session;

    // save the form data to a session
    $session->set('application', $this->_app);

    // create the quickbase table models objects
    $this->_QuickBaseModels['GenFnHome\Application'] = new GenFnHome\Application();
    $this->_QuickBaseModels['GenFnHome\SSN'] = new GenFnHome\SSN();
  }

  public function process()
  {
    $this->_existingApp = $this->_getExistingApplication();

    $app_status = $this->_existingApp[GenFnHome\SSN::LogInApplicationStatus];

    if(!$this->_existingApp || ($this->_existingApp && ($app_status !== 'PENDING' && $app_status !== 'OPEN' && $app_status !== 'EXPIRED')))
      return $this->_saveNewLoanApplication();

    if($app_status == 'EXPIRED') $this->_reOpenApplication();
  }

这里有很多内容,所以我先概述一下:

  • 用户提出申请
  • 申请表已经过验证
  • 如果有效,请处理贷款申请
  • 检查用户是否已有应用程序,如果是 - 执行X,如果不是Y
  • 应用程序保存在我的应用程序通过HTTP通过XML进行通信的“在线数据库”(QuickBase)中(换句话说,没有真正的数据库)

我向社区提出的问题:

  • 这里应该测试什么?我知道这在很大程度上取决于我,但也许社区可以推荐一些应该编写的基线测试。我应该测试控制器,处理器类和QuickBase类吗?
  • 我的测试是否应该彼此独立 - 这意味着,我应该单独测试每个组件,而不是使用一个大型的testApplication来完成indexAction所做的一切,只是查找设置的预期会话变量?
  • 最后,一个测试API如何调用(请求/响应)而不实际发出实际请求(我正在使用PHPUnit)。
  • 还有什么我应该知道的吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

  

这里应该测试什么?我知道这在很大程度上取决于我,但也许社区可以推荐一些应该编写的基线测试。我应该测试控制器,处理器类和QuickBase类吗?

我建议您测试您构建的每个课程。如果您正在使用测试驱动开发,那么测试将声明您正在构建的内容,而不是测试没有代码。

  

我的测试是否应该彼此独立 - 这意味着,我应该单独测试每个组件,而不是使用一个大型的testApplication来完成indexAction所做的一切,只是查找设置的预期会话变量?

每个单元测试都应该是隔离的,并且应该只测试您正在测试的类。如果一个对象依赖于另一个对象,则应该使用Mock对象(使用PHPunit模拟库或其他第三方库作为Mockery)。

  

最后,一个测试API如何在没有实际请求的情况下调用(请求/响应)(我正在使用PHPUnit)。

您可以使用Symfony的WebTestCase提供简单的方法来模仿浏览器请求,在the documentation中详细了解该信息。我们称之为功能测试。

这通常是单元测试后的阶段。在单元测试中,您将测试每个单独的类(这是unit test your controller的一个好习惯),之后您编写功能测试,如果它按预期工作,它将所有内容和测试结合起来。

答案 1 :(得分:0)

对于控制器,您应该使用功能测试(http://symfony.com/doc/2.0/book/testing.html#functional-tests)。使用它们,您可以模拟浏览器和用户的操作,如提交表单和检查验证,数据库更改,http状态代码等。

您不应忘记对ProcessLoanApplication进行单元测试。

我真的不知道为什么要将表单对象传递给ProcessLoanApplication。你应该传递实体 - 它已经有normdata。