5

The following script both demonstrates and documents (in the header comment) the issue, namely that I am unable to detect any difference between the "expected" and "actual" strings:

<?php

/*
$ phpunit MyTest.php
PHPUnit 3.4.0 by Sebastian Bergmann.

F

Time: 0 seconds

There was 1 failure:

1) MyTest::test_print_r
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-O:7:"MyClass":2:{s:13:"MyClassvar3";N;s:4:"var1";N;}
+O:7:"MyClass":2:{s:13:"MyClassvar3";N;s:4:"var1";N;}

.../MyTest.php:41
.../bin/phpunit:54

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
*/

class MyClass {
    static protected $var2;
    private $var3;
    public $var1;

    public function foo($item) {
        echo $item . "\n";
    }
}

class MyTest extends PHPUnit_Framework_TestCase {
    function test_print_r() {
        $m = new MyClass();
        $this->assertEquals(trim('O:7:"MyClass":2:{s:13:"MyClassvar3";N;s:4:"var1";N;}'), trim(serialize($m)));
    }
}

1 Answer 1

10

You don't see the Problem because you are using a quite old PHPUnit Version. The current version is 3.6.5 and if you can you should upgrade.

PHPUnit > 3.6 will show a differnt diff to you when the string contains unprintable characters. As is the case here.

Here is the output using a more current Version. The explanation on why it fails is below:

phpunit
PHPUnit 3.6.5 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 3.25Mb

There was 1 failure:

1) MyTest::test_print_r
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'O:7:"MyClass":2:{s:13:"MyClassvar3";N;s:4:"var1";N;}'
+Binary String: 0x4f3a373a224d79436c617373223a323a7b733a31333a22004d79436c6173730076617233223b4e3b733a343a2276617231223b4e3b7d

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

Explanation

A serialized php string contains NULL BYTES to denote private and protected class variables.

The string "MyClassvar3" is really "\0MyClass\0var3".

To fix the assertion:

$this->assertEquals(
    "O:7:\"MyClass\":2:{s:13:\"\x00MyClass\x00var3\";N;s:4:\"var1\";N;}",
    serialize($m)
);

Using this will result in the test working.


Sign up to request clarification or add additional context in comments.

5 Comments

+1 for a perfect answer. I'll mark it as "accepted" as soon as I verify the behavior in my test environment.
Unfortunately, I am unable (due to Circumstances Beyond My Control) to upgrade my official test environment to PHP 5.3, which is required by PHPUnit 3.6. But the answer is valid, and therefore accepted.
@Peter No PHPUnit 3.6 works with PHP 5.2.7 and upwards. (It works fine with 5.2.6 too from what i can tell). phpunit --force --alldeps phpunit/phpunit. The first PHPUnit version that will require PHP 5.3 is PHPUnit 3.7 and that is not going to be released for some time.
I'm happy to hear the news that PHPUnit 3.6 does not actually require PHP 5.3 (as I'm stuck on PHP 5.2.17 for the time being). I somehow misread "PHPUnit 3.6 requires PHP 5.2.7 (or later) but PHP 5.3.8 (or later) is highly recommended." in Chapter 3 of the Manual. Thanks!
the protected property, the string "*var3" is really "\x00*\x00var3", in vim you can type NULL BYTES with <Ctrl-v>000 in inster mode.

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.