Jplus2 Jplus2 - 5 months ago 19
Ajax Question

WP_Ajax_UnitTestCase does not throw WPAjaxDieStopException

Ok so I am testing my ajax callbacks for my wordpress plugin.
So I basically followed instructions here
https://codesymphony.co/wp-ajax-plugin-unit-testing/

Here is my ajax callback function

public function my_plugin_get_site_pages( $args = null ) {

//...... Processing $site_pages.....

$response = array(
'status' => 'success',
'site_pages' => $site_pages
);

@header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
echo wp_json_encode( $response );
wp_die();

}


Here is my test

class My_Plugin_Ajax_Test extends WP_Ajax_UnitTestCase {

private $_foo;

public function setup() {

//.....Initialize $_foo here...

}

public function test_foo() {

try {

$_POST[ 'args' ] = array( 'return_format' => 'raw' );

add_action( 'wp_ajax_my_plugin_get_site_pages' , array( $this->_foo , 'my_plugin_get_site_pages' ) );

//$this->setExpectedException( 'WPAjaxDieStopException' );
$this->_handleAjax( 'my_plugin_get_site_pages' );

} catch ( WPAjaxDieStopException $e ) {}

//$response = json_decode( $this->_last_response );
$response = $this->_last_response;
var_dump( $response );

}

}


Now here are the issues


  1. It doesn't throw WPAjaxDieStopException exception like its suppose to



when I do this code
$this->setExpectedException( 'WPAjaxDieStopException' );

it fails the test https://snag.gy/JSTqHV.jpg


  1. It prints out that wp_die() has been triggered, so this code



$response = $this->_last_response;
var_dump( $response );


prints this

https://snag.gy/pKqfUk.jpg

Number 2 is an issue because you cannot do
json_decode
the string outputted coz its an invalid json string, so I can't continue with my test.

I'm just starting out with automated testing on wordpress plugins and I appreciate any help.

Note:
My ajax callback is working ok on my live plugin even if I use wp_die(), it just prints that weird 'wp_die called ...' string on my test.

My php version is 5.6.21 and my phpunit version is 4.8.26




Here are some additional info

So both 'WPAjaxDieStopException' and 'WPAjaxDieContinueException' are not thrown,

however what's interesting is when I do this

$this->_setRole( 'administrator' );


I get this error on the console

Trying to get property of non-object

/tmp/wordpress-tests-lib/includes/testcase-ajax.php:151
/vagrant/www/wordpress/wp-content/plugins/my-plugin/tests/test-file.php:30


But clearly I'm extending WP_Ajax_UnitTestCase and it has the _setRole method
https://core.trac.wordpress.org/browser/trunk/tests/phpunit/includes/testcase-ajax.php#L168

Also when I run phpunit I get this bunch of errors or warnings on the console

Installing...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
WordPress database error Duplicate key name 'location_type_code' for query ALTER TABLE wptests_woocommerce_tax_rate_locations ADD KEY location_type_code (location_type(40),location_code(90)) made by PHPUnit_TextUI_Command::main, PHPUnit_TextUI_Command->run, PHPUnit_TextUI_Command->handleArguments, PHPUnit_TextUI_Command->handleBootstrap, PHPUnit_Util_Fileloader::checkAndLoad, PHPUnit_Util_Fileloader::load, include_once('/vagrant/www/wordpress/wp-content/plugins/my-plugin/tests/bootstrap.php'), require('/tmp/wordpress-tests-lib/includes/bootstrap.php'), require_once('wp-settings.php'), do_action('init'), call_user_func_array, WC_Install::check_version, WC_Install::install, WC_Install::create_tables, dbDelta


Also I am using vagrant and use http://vccw.cc/ for my dev env and also following this guide on adding tests for woocommerce extensions
https://github.com/Automattic/wc-extensions-code-test-guide

Hope all this additional info will help in finally solving this issue.

Answer

Been away for a while, been very busy, finally got some time to figure this out. It turns out it's a stupid mistake (facepalm).

Since we are using WP_Ajax_UnitTestCase which extends WP_UnitTestCase

Then when we use function setup in WP_Ajax_UnitTestCase then we need to call this parent::setup();

public function setup() {
    parent::setup();
    // your init codes here
}

I was not calling that on my existing code that's why the test is acting weird. Adding that solves all the weird issues and runs the test as expected and throws necessary exceptions.

WPAjaxDieStopException is thrown if ajax callback function does not yield any output.

WPAjaxDieContinueException is thrown if ajax callback yields any output.

Also make sure to use wp_die() instead of die() on your ajax callback, if you use the later, the test will halt.

I am planning to write and extensive guide to doing automated testing in WordPress plugins, I'll put the link to it here soon.

For now I hope this helps anyone.

Comments