简体   繁体   中英

PHPUnit test cases

I'm very new to Unit testing; I need to use PHPUnit test to write test cases! Since I have not seen any test cases, I do not know exactly how I can test, how I can write test cases... If you can help me to test one of my small methods, I can get a good vision of testing and understand the logic. So I was wondering if you would mind helping me with testing the following method (perferably with PHPUnit, but any other testcases can help me to understand the logic as well):

static public function get_accepted_images($limit, $page, $uuid) {

    try {
        $conn = new pdo_connect();

        $query = "  SELECT ....";

        $result = $conn->prepare($query);
        $result->bindParam(':uuid', $uuid);
        $result->execute();
        $array_result = $result->fetchAll(PDO::FETCH_OBJ);
        $paginate_result = WS_Utility::paginate_array($array_result, $page, $limit);
        $result_Set = array($paginate_result, TRUE);
    } catch (Exception $e) {

        $result_Set = array($e->getMessage(), FALSE);
    }


    return $result_Set;
}

If you need more clarification, please let me know and your help is totally appreciated!

You cannot unit test this method, because it has too many side effects. Especially the result will differ depending on the database selected.

To test this method, you will need to do functional testing. This is not much different from unit testing (and can be done by phpunit too, but you need to prepare the database before running the test. That way, you will get a predictable result and you can test the logic of your function.

I do not see much sense in testing the above method, but I suggest to rather test WS_Utility::paginate_array() , because this one is the only function call that does any logic, besides fetching from DB of course.

First you should change this method to non-static.

public function get_accepted_images($limit, $page, $uuid) {
    try {
        $conn = new pdo_connect();
        $query = "SELECT...";
        $result = $conn->prepare($query);
        $result->bindParam(':uuid', $uuid);
        $result->execute();
        $array_result = $result->fetchAll(PDO::FETCH_OBJ);
        $paginate_result = WS_Utility::paginate_array($array_result, $page, $limit);
        $result_Set = array($paginate_result, TRUE);
    } catch (Exception $e) {
        $result_Set = array($e->getMessage(), FALSE);
    }
    return $res;
}

Next thing is work on this method with some integration testing (NOT UNIT TESTING).
When you do integration testing you don't care how the method is implemented, but you should know precisely the contract of the method (for ex: on this input ill receive this output, on this context ill receive this exception, etc etc)

Based on this knowledge of this method contract you start doing the integration tests:

class ImageDatabaseHelperIntegrationTest extends PHPUnit_Framework_TestCase
{
//The most simple test. When no images exists in the DB what happens?
public function testWhenNoImagesExistsReturnCorrectResult() {
    $sut = new ImageDatabaseHelper(); //I dont know what is the name of the class
    $actual = $sut->get_accepted_images(1,1,1);
    $expected = array(null, FALSE); //?? I dont know what the result is. you know this
    $this->assertEquals($expected, $actual);
}


//You should keep doing like this. 
//The next tests will include inserting data in the database, and testing what is the output




EDIT:

user3421904 wrote : But why not static? Cant we do it like: $actual = images::get_accepted_images(1, 1, 11); this one works on my end as well! Is it wrong?

Is not wrong. But if you are going to unit test other component that consumes ImageDatabaseHelper you will not be able to mock it. Here is why:

Let's say that you are using an ImageService class which consumes directly the get_accepted_images static method. Like this:

class ImageService {

    public function getAcceptedImages() {
        $images = ImageDatabaseHelper::get_accepted_images(1,1,1);

        //...
        //more code 
        //...

        return $images;
    }
}

How do you test the getAcceptedImages method without accessing the DB? You can't, right?

Now imagine that you do the method non-static.

class ImageService {
    private $imageDatabaseHelper;

    public function __construct(ImageDatabaseHelper $imageDatabaseHelper = null) {
       if(!$imageDatabaseHelper) {
          $this->imageDatabaseHelper = new ImageDatabaseHelper();
       }
       else {
          $this->imageDatabaseHelper = $imageDatabaseHelper;
       }
    }


    public function getAcceptedImages() {
        $images = $this->imageDatabaseHelper->get_accepted_images(1,1,1);

        //...
        //more code 
        //...

        return $images;
    }
}

This can be tested easily!!!

class ImageServiceTest extends PHPUnit_Framework_TestCase {
    protected $sut;    

    protected $imageDatabaseHelperDouble;

    public function setUp() {
      $this->imageDatabaseHelperDouble = $this->getMockBuilder('ImageDatabaseHelper')->disableOriginalConstructor()->getMock();
      $this->sut = new ImageService($this->imageDatabaseHelperDouble);
    }


    public function testGetAcceptedImagesWhenCalledShouldCallImageDatabaseHelper() {
       $this->imageDatabaseHelperDouble->expected($this->once())->method('get_accepted_images')->with(1,1,1);
       $this->sut->getAcceptedImages();
    }


    public function testGetAcceptedImagesWhenCalledShouldReturnImages() {
       $this->imageDatabaseHelperDouble->expected($this->any())->method('get_accepted_images')->will($this->returnValue(array("hi im an image", "me tooo")));
       $actual = $this->sut->getAcceptedImages();

       $expected = array("hi im an image", "me tooo");
       $this->assertEquals($expected, $actual);
    }

}

You see? The mocked ImageDatabaseHelper overrides the original ImageDatabaseHelper used by ImageService and he thinks he is using it. From this you can do whatever you want! (this also includes making ImageDatabaseHelper throw exceptions!)

Have fun!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM