PHPUnit模拟对象是否可以替换类中创建的对象


Is it Possible to PHPUnit Mock Object to Replace one Created in Class?

我一直在尝试让PHPUnit模拟对象为我正在处理的一些遗留代码工作,但我在为我想要的对象提供子对象时遇到了问题,我很确定这一定是因为我使用错了。

目前,我们有一个纯粹用于创建查询的类,当另一个类想要进行查询时,它会创建该类的对象,并将sql和数据库详细信息传递给它。我想做的是让PHPUnit用一个我可以测试的模拟版本来替换这个对象。

不过,我发现,如果我在测试脚本中创建mock对象,那么被测试的方法就会绕过它。我猜这是因为该方法是在本地创建并使用对象,而不是将其作为参数传递(在这种情况下,我可以将mock对象作为参数传递来引用该方法)。下面是代码的一个示例:

class SampleClass{
    function loadData(){
        $sql = "SELECT * FROM users";
        $query = new Query();
        $query->query($sql);
        while($row = $query->get_row()){
            if($row['email'] = ''){
                $this->errors[] = "Email missing from user ".$row['user_id'];
            }
            $result[] = $query->get_row();
        }
        $this->users = $result;
        if(count($user->errors) >= 1){
            return $user->errors;
        }else{
            return true;
        }
    }
}
class Query{
    function query($sql){
        $this->result = mysql_query($sql);
    }
    function get_row(){
        return mysql_fetch_assoc($this->result);
    }
}

有没有一种方法可以在PHPUnit测试文件中创建一个mock对象,用一个我可以用来测试传递给的参数并控制其响应的mock对象来替换SampleClass中的$query对象?我将无法替换查询类或更改它的引用方式,因为它在我们的应用程序中被广泛使用,但我希望至少能够为它创建某种形式的测试框架。如果您能为提供任何帮助,我将不胜感激

经过编辑以澄清loadData方法中发生的不仅仅是查询,它是我试图测试的方法的一部分。我希望对查询类方法get_row进行双重细分,该方法将返回一个预设的样本数据数组供该方法使用,而不是访问实际的数据库

是的,这是可能的。

不过,您可以创建一个自己的SampleClass存根。您也可以使Query的类名或实例成为依赖项。所以你实际上可以注入它。我认为这是一种更好的方法,对你来说更容易编写测试。