我的目标是能够为倡导静态方法的单元测试编写单元测试:
约束:我们不能将静态方法重构为实例方法。我可能会建议这是第一件事,但是我正在寻找一种选择/替代方案和意见。
测试静态方法有点麻烦。曾经有一段时间我们可以使用phpunit做到这一点。 Mockery支持通过static methods测试aliasing的方法,但不建议这样做。我发现运行这些类型的测试可能非常慢。 (因此,目标2)。
[不幸的是,如果您有相当数量的代码依赖于使用静态方法的其他代码,则您将承担自己的债务。有一些使用call_user_func
(https://medium.com/@nihon_rafy/how-to-mock-static-methods-for-unit-tests-in-php-18b2a11458d0)和forward_static_call_array()
(http://miljar.github.io/blog/2014/01/29/phpunit-testing-static-calls/)的技术,但我发现自己很难遵循此代码。
我想提供替代动态选项,类似于上面的内容。
class LegacyClass {
public static function staticMethod($a, $b, $c) {
return QueryBuilder::where($a, $b, $c)->getAll();
}
}
class ClassToTest {
public function test($a, $b, $c) {
return LegacyClass::staticMethod($a+1, $b+2, $c+3);
}
对此的更改=>
class LegacyClass {
public static function staticMethod($a, $b, $c) {
return QueryBuilder::where($a, $b, $c)->getAll();
}
}
class ClassToTest{
// @var string fully qualified class name
private $legacyClass = LegacyClass::class;
public function test($a, $b, $c) {
return {$this->legacyClass}::staticMethod($a+1, $b+2, $c+3);
}
现在,通过以上操作,我们可以模拟LegacyClass
,获取该模拟的类名,并使用Reflection
设置私有$legacyClass
变量。
关于这个,我的问题:
谢谢您的输入!
我经常回想的解决方案是创建“中间人”类。我将其用于静态函数调用,还用于在代码中间创建new Object();
的情况。
本质上,您只是将问题转移到了其他地方,这看起来似乎不是一个很好的解决方案,但是您只需将一行移开即可使ClassToTest
易于测试。
简而言之;我要上一个新课(StaticFunctionCallerClass
)。该类只有一个函数,只有一行。
class StaticFunctionCallerClass {
public function test($a, $b, $c) {
return LegacyClass::staticMethod($a+1, $b+2, $c+3);
}
现在您可以在ClassToTest
中实例化此类(因此可以在测试中对其进行模拟)。因此,您可以测试其周围的所有逻辑,甚至可以测试是否使用正确的信息调用了新的StaticFunctionCallerClass
。
这里的缺点是它使新的StaticFunctionCallerClass
难以测试代码。您可以在LegacyClassTest
中调用此类,以测试调用是否正确完成,这也许不是一个很干净的选择,但确实可以完成工作。