Merianos Nikos Merianos Nikos - 1 month ago 11
PHP Question

PHPUnit | Testing json return

I am very new on PHPUnit testing, and I need some help if posible.

I have install a plugin in WordPress, for unit testing, that is based on PHPUnit Framework. I am currently building a WordPress Plugin that using AJAX calls, in order to interact with the WordPress data.

In my plugin, I have create a Class that creating some add_action('wp_ajax_actionname', array(__CLASS__, 'functionName'))

the functionName looks like the following:

function functionName()
{

global $wpdb;

if(wp_verify_nonce($_POST['s'], 'cdoCountryAjax') != false)
{
$zones = $wpdb->get_results(
$wpdb->prepare(
"
SELECT
zone_id AS ID,
name AS Name
FROM
" . $wpdb->prefix . "cdo_zone
WHERE
country_id = %d
",
$_POST['id']
)
);

header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Content-type: application/json');

$results = array();

foreach($zones as $zone)
{
$results[$zone->ID] = $zone->Name;
}

echo json_encode($results);
}

die(-1);

}


The above function it gets the Query results returned into an Object, and I echoed by using the json_encode function.

The question is, how can I test the above method ? Is there a way to test it ?

Answer

There are two not-so-test-friendly things you will have to deal with:

The output generation with echo. For this, you can wrap the function call in question inside an ob_start() ... ob_end_clean() pair to get the output that would have been echoed.
Edit:
As it turns out, there's already a built-in support for this in the library, check out the Testing Output section of the manual.

The other problem you have to deal with is the die(-1) at the end. You can use the set_exit_overload() function provided in php test helpers to disable it's effect, so your test process won't die along with the code. This is a little harder to set up (you will need a C compiler). If that can't work for you you could be out of luck in case you can't change the code to something more test friendly. (I'm not too familiar with wordpress but for ajax plugins this die() usage seems recommended). As a last resort, you could try running the script as a subprocess with popen() or exec() and get the result that way (you will have to write a file that includes the source and calls the function that will not be tested).

In the ideal case this would look something like this:

function test_some_wp_plugin_test() {
    // deal with the die()
    set_exit_overload(function() { return false; });

    // set expectation on the output
    $expected_result = array('foo' => 'bar');
    $this->expectOutputString(json_encode($expected_result));

    // run function under the testing
    function_in_test();
}

In the worst case, maybe something like:

function test_some_wp_plugin_test() {
    $output = array();
    // you will need cli php installed for this, on windows this would be php.exe at the front
    $results =  exec('php tested_function_runner.php', $output);
    // start asserting here
}

And inside the tested_function_runner.php:

include 'path/to/the/plugin.php';
function_under_test();

You can of course make this runner script more general with parameters passed and used from $argv.

Comments