doremi
doremi

Reputation: 15329

How do I write test(s) for this in Symfony?

I'm about to delve into test in the PHP world and I have some questions. I have a controller which handles a loan application. The bulk of the work is then delegated to a ProcessLoanApplication class.

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'));
        }
    }

Tasks\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();
  }

There's a lot going on here, so I will outline it first:

My questions to the community:

Thanks!

Upvotes: 1

Views: 487

Answers (2)

Wouter J
Wouter J

Reputation: 41934

What should be tested here? I know it is largely up to me, but perhaps the community can recommend some baseline tests that should def be written. Should I be testing the controller, the processor class, and the QuickBase class?

I recommend to test every class you build. If you are using Test Driven Development, the test declares what you are building, no test no code.

Should my tests be independent of one another - meaning, I should test each component individually, rather than have one massive testApplication that does everything the indexAction does and just looks for the expected sessions vars that get set?

Every Unit test should be isolated and should only test the Class that you are testing. You should use Mock object (use the PHPunit mock library or other 3th party libraries as Mockery) if one object dependences on another object.

Finally, how does one test API calls (request / response) without actually making real request (I'm using PHPUnit).

You can use the Symfony's WebTestCase that provides easy methods to imitate a browser request, learn more about that in the documentation. We call that Functional Testing.

This is usually the stage after Unit Testing. In Unit Testing you will test each individual class (it's a good practice to unit test your controller) and after that you write your Functional Tests which combines everything and tests if it works like expected.

Upvotes: 1

mrMantir
mrMantir

Reputation: 2285

for Controllers you should use functional tests (http://symfony.com/doc/2.0/book/testing.html#functional-tests). With them you can emulate browser and user's actions like submiting form and checking validation, database changes, http status codes and so on.

You should not forget to unit test ProcessLoanApplication.

I dont realy know why you pass form object to ProcessLoanApplication anyway. You should pass entity - it has normdata already.

Upvotes: 0

Related Questions