Php 如果仍然可以模拟对象,为什么服务定位器不适合测试?

Php 如果仍然可以模拟对象,为什么服务定位器不适合测试?,php,design-patterns,dependency-injection,Php,Design Patterns,Dependency Injection,每个人都知道,使用服务定位器的代码很难测试,而应该使用依赖注入 但是,如果我们仍然可以轻松地模拟每个对象,为什么服务定位器很难测试呢 考虑这个例子(用PHP编写,但可以是任何语言) 如果我们想测试这段代码,我们可以简单地模拟我们的对象“依赖关系”,例如: function testMyFunction() { $mock = \Mockery::mock('Dependency'); $mock->shouldReceive('doSomething')-

每个人都知道,使用服务定位器的代码很难测试,而应该使用依赖注入

但是,如果我们仍然可以轻松地模拟每个对象,为什么服务定位器很难测试呢

考虑这个例子(用PHP编写,但可以是任何语言)

如果我们想测试这段代码,我们可以简单地模拟我们的对象“依赖关系”,例如:

 function testMyFunction() {
        $mock = \Mockery::mock('Dependency');
        $mock->shouldReceive('doSomething')->once();

        Registry::set('Dependency', $mock); // set the double

        $workerObject = new MyClass;
        $this->assertTrue( $workerObject->myFunction() );
 }
这段代码不是可以测试的吗?为什么服务定位器在这种情况下不好


请注意,我们都知道服务定位器有多糟糕,因为它隐藏了依赖关系并违反了坚实的原则。但在本例中,我只是指测试方面。

在我的经验中,这主要是因为它会搞乱全局状态

在测试A的注册表中设置一些东西,总有一天它会搞乱测试B,您将花一整天的时间调试它

当然,如果每个测试都完全重置了所有内容,那么您可以将风险降至最低。但它会使您的测试套件速度变慢。再说一次,YMMV,但举个例子,在我正在进行的一个大项目中,这是一场噩梦

请注意,我们都知道服务定位器有多糟糕,因为它隐藏了依赖关系并违反了坚实的原则。但在本例中,我只是指测试方面

我发现很难测试隐藏其依赖性的东西。必须通过所有的代码才能知道我要嘲笑什么,这既无聊又浪费时间

使用依赖项注入,我只需键入
newclasstotest(
),IDE就会立即显示需要哪些依赖项

每个人都知道,使用服务定位器的代码很难测试,而应该使用依赖注入

我不知道

这并不是因为它使代码难以测试(事实并非如此),而是因为它使代码难以维护

服务定位器破坏了封装,因为您可以在代码中的任何位置使用它,而客户端如果不通读可能使用它的所有代码,就无法检测到这一点

依赖注入是一个更好的选择,因为它是

 function testMyFunction() {
        $mock = \Mockery::mock('Dependency');
        $mock->shouldReceive('doSomething')->once();

        Registry::set('Dependency', $mock); // set the double

        $workerObject = new MyClass;
        $this->assertTrue( $workerObject->myFunction() );
 }