Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 293
KodeFor.Me Avatar asked Dec 26 '22 01:12

KodeFor.Me


2 Answers

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.

like image 175
complex857 Avatar answered Jan 05 '23 15:01

complex857


When you feel like it, please also take a look at the Output Test features of PHPUnit, they are great.

(As complex857 said, there are many bits and pieces to this issue, but for the output testing, lean on this PHPUnit built-in feature.)

The manual is eloquent and helpful: https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.output

like image 25
olleolleolle Avatar answered Jan 05 '23 16:01

olleolleolle