PHP:如何创建可测试的静态方法
我决定制作自己的穷人ORM框架。因为我不知道该怎么做,所以我决定在测试前开发。在按照我想要的方式工作之后,我意识到我的代码是不稳定的,因为来自查询类和BaseModel的静态方法之间存在紧密耦合 所以我想了一些方法让它可以测试:PHP:如何创建可测试的静态方法,php,unit-testing,oop,static,Php,Unit Testing,Oop,Static,我决定制作自己的穷人ORM框架。因为我不知道该怎么做,所以我决定在测试前开发。在按照我想要的方式工作之后,我意识到我的代码是不稳定的,因为来自查询类和BaseModel的静态方法之间存在紧密耦合 所以我想了一些方法让它可以测试: 使每个查询方法都接收一个连接对象:但这意味着,当我尝试在BaseModel类中使用这些方法时,我仍然必须将连接对象与BaseModel紧密耦合 保持原样:这意味着在PHPUnit测试期间,我必须重写BaseModel 不管怎样,我觉得我做的事情不对。我相信有一个更好的方
如果您不想重写代码,不使用静态,请考虑在基类上添加查询类的属性,例如添加类似
的属性。public static function setQueryClass($className) {
static::queryClass = $queryClass;
}
然后将对StaticSQLQuery
的所有硬编码调用替换为对set$className
的调用。虽然这仍然有点难看,但它允许您在测试期间使用不同的类替换StaticSQLQuery
,例如,您可以将其放入测试中:
BaseClass::setQueryClass(
get_class(new class extends StaticSQLQuery {
public static function init()
{
return 'My stub';
}
})
);
在PHP7之前,您必须硬编码该类:
class StaticSQLQueryMock extends StaticSQLQuery
{
public static function init()
{
return 'My stub';
}
}
BaseClass::setQueryClass(StaticSQLQueryMock::class);
为了测试静态方法,我创建了自己的模拟库: 下面是如何使用它来测试静态代码的快速示例:
$classMock = \shagabutdinov\Moka::mockClass('MyClass', ['::method' => 'RESULT']);
$classMock::method('ARG1'); // RESULT
$classMock::method('ARG2'); // RESULT
$classMock::moka->report('method'); // [['ARG1', 'ARG2']]
快看一下你的代码,看看下面的文章。你可能需要重构一些东西。好的应用程序从技术设计开始,以避免出现问题并轻松实现单元测试等附加功能。我认为这个问题可能更适合codereview.stackexchange.com,而不是堆栈溢出。在回答您的问题时,由于许多原因,您基本上不能对依赖于静态的代码进行单元测试。您最好尽可能避免使用静态方法,并依赖其他技术,如依赖项注入(传入内容)。静态有时会有用途,但总的来说,它们造成的问题比解决的问题要多。@GordonM,是的,你是绝对正确的,如果你看我的第一个建议,它是针对依赖注入的,但最终必须消耗静态方法,这最终会导致紧密耦合。如果仔细观察,您会发现使用静态方法是有意义的,尤其是在使用BaseModel::getAll()时