PHPUnit - Use $this or self for static methods?

2020-02-24 13:29发布

问题:

I don't want to write a long text, because it is a short question. PHPUnit tests contain several methods that are static. For example all those \PHPUnit\Framework\Assert::assert*() methods and also the identicalTo, equalTo.

My IDE (with IntelliSense/autocompletion) doesn't accept calls with $this, but with self. I have learned that static functions should be called through the class, not an object, so self.

What is more correct?

$this->assertTrue('test');

or

self::assertTrue('test');

?

(And if "$this" is more correct, can you maybe point out why we should not use "self"?)

回答1:

Generally, self is only used to refer to static methods and properties (though confusingly you can refer to non-static methods with self, and to static methods with $this, provided the methods called with self don't reference $this.)

<?php
class Test {
    public static function staticFunc() {echo "static ";}
    public function nonStaticFunc() {echo "non-static\n";}
    public function selfCaller() {self::staticFunc(); self::nonStaticFunc();}
    public function thisCaller() {$this->staticFunc(); $this->nonStaticFunc();}
}
$t = new Test;
$t->selfCaller();  // returns "static non-static"
$t->thisCaller();  // also returns "static non-static"

Inheritance is important to remember when dealing with $this or self. $this will always refer to the current object, while self refers to the class in which self was used. Modern PHP also includes late static binding via the static keyword, which will operates the same way as (and should be preferred over) $this for static functions.

<?php
class Person {
    public static function whatAmI() {return "Human";}    
    public function saySelf() {printf("I am %s\n", self::whatAmI());}
    public function sayThis() {printf("I am %s\n", $this->whatAmI());}
    public function sayStatic() {printf("I am %s\n", static::whatAmI());}
}

class Male extends Person {
    public static function whatAmI() {return "Male";}
}

$p = new Male;
$p->saySelf();    // returns "I am Human"
$p->sayThis();    // returns "I am Male"
$p->sayStatic();  // returns "I am Male"

As regards PHPUnit in particular, it appears they simply do things the way they've always done them! Though according to their documentation, your code should work fine using static methods.



回答2:

PHPUnit 4.8.9: vendor/phpunit/phpunit/src/Framework/Assert.php:

/**
 * Asserts that a condition is true.
 *
 * @param bool   $condition
 * @param string $message
 *
 * @throws PHPUnit_Framework_AssertionFailedError
 */
public static function assertTrue($condition, $message = '')
{
    self::assertThat($condition, self::isTrue(), $message);
}

Technically static::assertTrue() is correct, but the common usage of the assert methods is $this->assertTrue().