0

How we can test a ajax call using phpunit zend.

This is my ajax call in controller

public function indexAction()
{   
    if ( $this->getRequest()->isPost() )
    {      

        if (self::isAjax()) {

            $name = $this->getRequest()->getParam('name');
            $email = $this->getRequest()->getParam('email');            


             $u = new admin_Model_User();
             $u->email = $email;
             $u->name = $name;             
             $u->save();

            if(!empty($u->id)) $msg = "Record Successfully Added";
            else $msg = "Records could not be added";


            $this->results[] = array('status'=>true, 'msg'=>$msg);


            echo $this->_helper->json($this->results);
        } else {
        echo "none-Ajax Request";
    }
    }else {

    echo "Request not post";
}
}

private function isAjax() {
    return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
}

here is my test case

    class AjaxjsonControllerTest extends ControllerTestCase
    {
    // testing not post area
    public function testIndexAction() {
        $this->dispatch('/ajaxjson');
        $this->assertModule('admin');
        $this->assertController('Ajaxjson');
        $this->assertAction('index');
    }
// testing not ajax request
public function testIndexNonajaxAction() {
        $request = $this->getRequest();  
      $request->setMethod('POST');
      $request->setPost(array(
        'name' => 'name bar',
        'email' => 'email x',
      ));

        $this->dispatch('/ajaxjson');
        $this->assertModule('admin');
        $this->assertController('Ajaxjson');
        $this->assertAction('index');
    }

        public function testPostAction() {
              $request = $this->getRequest();
              //$request->setHeader('X_REQUESTED_WITH','XMLHttpRequest');
              $request->setHeader('HTTP_X_REQUESTED_WITH','XMLHttpRequest');

              $request->setMethod('POST');
              $request->setPost(array(
                'name' => 'name bar',
                'email' => 'email x',
              ));

              $this->dispatch('/ajaxjson');
            }

    }

but this is not working. Has anyone an idea?

4
  • just to be clear that it is not covering the area in if condition Commented Mar 9, 2011 at 16:55
  • 2
    What's not working? I don't see an actual PHPUnit test case there. There are no checks to see if anything happens. Your test case looks to just fire off a curl request (I assume getRequest and dispatch are just zend wrappers) but not do anything with the response of the request. Commented Mar 9, 2011 at 17:05
  • phpunit is not covering the area between if (self::isAjax()) condition. If this is not the write way to test the ajax call actions. then which is best way to test ajax calls?? because of this it only give me the code coverage of 50% Commented Mar 9, 2011 at 17:12
  • Ok, can you try and define for us what you are actually trying to test. Are you trying to check if there is any response or if there is a specific response? Is it intentional that you're not covering the code inside the if condition or is that your problem? From the way you have worded things it's difficult to tell what you actually mean. Commented Mar 9, 2011 at 17:15

1 Answer 1

1

First, PHPUnit typically runs via the console. When I check the $_SERVER variable via tests that I run, it is a lot different than what would be found in a web server. In your isAjax method, you should use something like:

$this->getRequest()->getHeaders() // array of headers
$this->getRequest()->getHeader('HTTP_X_REQUESTED_WITH'); //specific header

If you really, really want to use $_SERVER in your controller, then why not just set the $_SERVER variable in the test?

$_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
      $request->setMethod('POST');
          $request->setPost(array(
            'name' => 'name bar',
            'email' => 'email x',
          ));
$this->dispatch('/ajaxjson');

Secondly and more importantly, you are not actually testing anything... You should have an assert in the test method. At it's most basic, you can use

   $this->assertController('ajaxjson');
   $this->assertAction('index');

But you really should be setting up multiple tests for this action. A test for

  1. when the request is not a post
  2. When request is not ajax
  3. when user is saved
  4. when user is not saved
Sign up to request clarification or add additional context in comments.

4 Comments

Hi RobertlBolton, many thanks it is working fine now. you describe very well. Last thing, can you explain what is best way to test last 4 points which you mentioned please.
for testing no-ajax request (number 2 in list above) I wrote this function. is this right way of testing it. public function testIndexNonajaxAction() { $request = $this->getRequest(); $request->setMethod('POST'); $request->setPost(array( 'name' => 'name bar', 'email' => 'email x', )); $this->dispatch('/ajaxjson'); $this->assertModule('admin'); $this->assertController('Ajaxjson'); $this->assertAction('index'); }
How we will write the test case for user not saved?
How you test depends on what you expect to take place when it is not a POST or not an AJAX request. Right now, you are just echo'ing out a message, which isn't really testable, nor likely the best solution. I would throw an expception if it's not a $_POST or Ajax call. That was, it is forwarded to your error controller, where you can log it, or take some other action. You can also test it, by ensuring the Error controller was called: $this->assertController('error'); To test save, look at Zend_Test_PhpUnit_Db. To test not saving, mock the User class and have it not set the id.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.