如果仍然可以模拟对象,为什么服务定位器不利于测试?
Why Service Locator is bad for testing if one can still mock objects?
每个人都知道使用服务定位器的代码很难测试,而应该使用依赖注入。
但是如果我们仍然可以轻松地模拟每个对象,为什么服务定位器很难测试呢?
考虑这个例子(用PHP写的,但它可以是任何语言)
// method we want to test that has a dependency
public myFunction() {
$someDependency = Registry::getService('Dependency');
// do something with the dependendcy
$someDependency->doSomething();
return true;
}
如果我们想测试这段代码,我们可以简单地模拟我们的对象 "Dependency",示例:
function testMyFunction() {
$mock = \Mockery::mock('Dependency');
$mock->shouldReceive('doSomething')->once();
Registry::set('Dependency', $mock); // set the double
$workerObject = new MyClass;
$this->assertTrue( $workerObject->myFunction() );
}
这段代码不是可测试的吗?为什么服务定位器在这种情况下不好?
请注意,我们都知道服务定位器有多糟糕,因为它隐藏了依赖性和紫罗兰色 SOLID 原则。但在这种情况下,我只是指测试方面。
根据我的经验,这主要是因为它弄乱了全局状态。
在测试 A 的注册表中设置一些东西,有一天它会搞砸测试 B,你将花费一整天的时间来调试它。
当然,如果每次测试都完全重置所有内容,那么您可以将风险降至最低。但它会使您的测试套件变慢。同样,YMMV,但是例如在我正在处理的一个大项目中这是一场噩梦。
Note that we all know how bad a Service locator because it hides dependency and violets SOLID principles. But in this case i am simply referring to the testing aspect.
我发现很难测试隐藏其依赖关系的东西。必须通过所有代码才能知道我必须模拟什么,这很无聊而且浪费时间。
通过依赖注入,我只需输入 new ClassToTest(_
,IDE 会立即显示需要哪些依赖项。
Everyone knows that code that uses Service Locator is hard to test while Dependency Injection should be used instead.
我不知道...
Service Locator is an anti-pattern 的原因不是因为它使代码难以测试(事实并非如此),而是因为它难以维护。
服务定位器破坏了封装,因为您可以在代码中的任何地方使用它,如果不通读所有可能使用它的代码,客户端就没有机会检测到这一点.
依赖注入是更好的选择,因为它solves the same problems with fewer disadvantages.
每个人都知道使用服务定位器的代码很难测试,而应该使用依赖注入。
但是如果我们仍然可以轻松地模拟每个对象,为什么服务定位器很难测试呢?
考虑这个例子(用PHP写的,但它可以是任何语言)
// method we want to test that has a dependency
public myFunction() {
$someDependency = Registry::getService('Dependency');
// do something with the dependendcy
$someDependency->doSomething();
return true;
}
如果我们想测试这段代码,我们可以简单地模拟我们的对象 "Dependency",示例:
function testMyFunction() {
$mock = \Mockery::mock('Dependency');
$mock->shouldReceive('doSomething')->once();
Registry::set('Dependency', $mock); // set the double
$workerObject = new MyClass;
$this->assertTrue( $workerObject->myFunction() );
}
这段代码不是可测试的吗?为什么服务定位器在这种情况下不好?
请注意,我们都知道服务定位器有多糟糕,因为它隐藏了依赖性和紫罗兰色 SOLID 原则。但在这种情况下,我只是指测试方面。
根据我的经验,这主要是因为它弄乱了全局状态。
在测试 A 的注册表中设置一些东西,有一天它会搞砸测试 B,你将花费一整天的时间来调试它。
当然,如果每次测试都完全重置所有内容,那么您可以将风险降至最低。但它会使您的测试套件变慢。同样,YMMV,但是例如在我正在处理的一个大项目中这是一场噩梦。
Note that we all know how bad a Service locator because it hides dependency and violets SOLID principles. But in this case i am simply referring to the testing aspect.
我发现很难测试隐藏其依赖关系的东西。必须通过所有代码才能知道我必须模拟什么,这很无聊而且浪费时间。
通过依赖注入,我只需输入 new ClassToTest(_
,IDE 会立即显示需要哪些依赖项。
Everyone knows that code that uses Service Locator is hard to test while Dependency Injection should be used instead.
我不知道...
Service Locator is an anti-pattern 的原因不是因为它使代码难以测试(事实并非如此),而是因为它难以维护。
服务定位器破坏了封装,因为您可以在代码中的任何地方使用它,如果不通读所有可能使用它的代码,客户端就没有机会检测到这一点.
依赖注入是更好的选择,因为它solves the same problems with fewer disadvantages.