如何使用PHPUnit测试方法是否为私有

Using PHPUnit, I would like to test that a Class CANNOT be instantiated using the __construct [ new Class(); ] method as well as cannot be cloned, woken up etc.

Basically it is a Singleton class, and the __construct, __clone and __wakeup methods set to private to make sure it remains a Singleton.

But how can I test for that?

You can do this by catching the exception thrown by trying to instantiate a new object from the singleton.

Try the following (PHP 7):

class Single
{
    private function __construct() {}
}

class SingleTest extends \PHPUnit_Framework_TestCase
{
    function testCannotCallConstructor()
    {
        try {
            $single = new Single();
            $this->fail('Should never be called!');
        } catch (\Throwable $e) {
            $this->assertNotEmpty($e->getMessage());
        }

        //alternative:
        $this->expectException(\Error::class);
        $single = new Single();
    }
}

By design, unit test usually checks a behavior, not an interface (method signature is a part of the interface).

But if you really need that you can use the Reflection API. Check the class hasMethod() and this method isPrivate().

In the PHP7 enviroment you can use try/catch solution proposed by John Joseph, but i recommend to intercept only Error exceptions (Throwable covers all possible erros, not only visibility violation). Also PHPUnit has a @expectedException annotation, it's better than manual try/catch.

All of these are working perfectly.

function testCannotCallConstructor()
{
    try {
        $log = new Log();
        $this->fail('Should never be called!');
    } catch (\Throwable $e) {
        $this->assertNotEmpty($e->getMessage());
    }

    //alternative:
    $this->expectException(\Error::class);
    $log = new Log();
}



public function testConstructPrivate(){
    $method = new \ReflectionMethod('\\Core\\Log', '__construct');
    $result = $method->isPrivate();
    $this->assertTrue( $result, "Log __construct is not private. Singleton not guaranteed.");
}

Thank you very much. I think the one I prefer is the expectException method.