外观并不能解决您提到的大命名空间问题。使用别名解决大名称空间。你可以在 config/app.php 中声明它们,当你调用它们时,Laravel 在内部将使用 class_alias。这就是例如\Cache 或 \DB 工作。
外观基本上是另一个类的单例对象实例的代理类(外观本身确保实例是单例)。
通常在 Laravel 中注册一个单身人士:
- 在您的服务提供商中添加
app()->singleton(ABC::class)
- 通过
app()->make(ABC::class)->...访问它
如果您尚未将该类注册为单例,则外观基本上会为您处理。
基本上,外观是代理另一个类的单例实例的一种方式。
此外,通常不可能模拟或存根静态方法,但是如果您使用门面,则可以使用 \ABCFacade::swap($mockObject),因此可以模拟您的门面。
不能测试静态方法也是错误的。您绝对可以测试静态方法。例如:
public testStaticMethod() {
$this->assertEquals(1, ABC::method()); // We tested a static method against a desired behaviour
}
您通常不能模拟静态方法。以下是您通常使用 PHPUnit 模拟某些东西的方式:
public testWithDependency() {
$dependency = $this->getMockBuilder(Dependency::class)->getMock();
$dependency->expects($this->once())->method('dependantMethod')->willReturn(true);
$objectToTest = new ABC($dependency); //We're passing a fake dependency which behaves in an ideal way
$this->assertEquals(1, $objectToTest->methodToTest()); //Any calls to the dependency will call mock methods and not real ones
}
尝试模拟静态方法时会出现问题。如您所见,模拟创建了某种类型的模拟 instances。它不能模拟该类型的静态成员,因为模拟对象本身实际上不是该类型。
但是,正如我刚刚发现不能模拟或存根静态方法的说法并不完全正确。 AspectMock 可以模拟静态方法或辅助方法。这似乎可以通过自定义自动加载器拦截所有函数调用来工作。
话虽这么说,仅仅因为你可以并不意味着使用静态方法是一种好习惯,还有其他问题需要考虑,例如您通常不能在大多数编程语言中拥有静态接口,或者您通常不能在大多数编程语言中覆盖静态方法。请注意此处的“在大多数编程语言中”部分。在 PHP 中,完全可以使用 late static binding 覆盖静态方法,但这意味着您在实现静态方法时需要对此做出有意识的决定。
另一个缺点是静态类不能实现接口,因为接口适用于对象行为而不是静态行为。因此,如果您使用静态,则不能将一个接口换成另一个接口,这是一个主要缺点。
一般来说,对静态方法的厌恶不是因为可测试性,而是因为如果您在 OOP 中编码,那么如果您使用静态方法,那么您真的会受到限制。
希望这将有助于消除一些困惑。