Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I've been trying to get the PHPUnit mock objects working for some legacy code I'm working on, but I'm having issues getting it to sub in for the object I'm after and I'm pretty sure it must be because I'm using it wrong.

Currently we have a class which is used purely for creating queries, when another class wants to make a query it creates an object of this class and passes it the sql and database details. What I want to do is have PHPUnit replace this object with a mock version which I can test.

What I've been finding though is, if I create the mock object in the test script, the method being tested just bypasses it. I'm guessing this is because the method is creating and then using the object locally rather than it being passed as a parameter (in which case I could just reference the method with the mock object passed as a parameter). Below is an example of what the code might look like:

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);
    }
}

Is there a way to create a mock object in the PHPUnit test file which will replace the $query object in SampleClass with a mock object which I can use to test the parameters being passed to and control the response of? I won't be able to replace the query class or change how it's referenced, as it's used extensively throughout our application, but I would like to at least be able to create some form of test framework for it. Would appreciate any help you can give

Edited to clarify that there's more than just the query happening in the loadData method, which is the part of the method I'm trying to test. I'm hoping to sub in a double of the query class method get_row which will return a pre-set array of sample data for the method to work with rather than it hitting an actual database

like image 579
SolidSquid Avatar asked Jul 09 '12 16:07

SolidSquid


1 Answers

Yes that is possible.

However, you can just create a stub of the SampleClass your own. And you can make the classname or instance of Query a dependency, too. So you can actually inject it. I'd say that's a better way and much easier for you to write tests then.

like image 59
hakre Avatar answered Nov 12 '22 10:11

hakre