1

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:

  • User makes a requests for the application
  • Application form is validated
  • If valid, process loan application
  • Check if the user already has an app, if so - do X, if not Y
  • The application is persisted in an 'online database' (QuickBase) that my application communicates with via XML over HTTP (in other words, there is no real db)

My questions to the community:

  • 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?
  • 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?
  • Finally, how does one test API calls (request / response) without actually making real request (I'm using PHPUnit).
  • Anything else I should know?

Thanks!

doremi
  • 14,921
  • 30
  • 93
  • 148

2 Answers2

1

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.

Wouter J
  • 41,455
  • 15
  • 107
  • 112
  • Looks like answer needs update - in that blog he does not think anymore that it is good to unit test the controller. http://php-and-symfony.matthiasnoback.nl/2012/06/symfony2-testing-your-controllers/ – Darius.V Jul 06 '23 at 15:11
0

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.

mrMantir
  • 2,285
  • 1
  • 17
  • 20