unit-testing – 如何对数据库插入函数PDO进行单元测试

在下面的代码中,我应该如何编写单元测试?

我该如何模拟数据库?嘲笑有什么意义?想象一下,在同一个保存类中,我们有一个注入数据库依赖的setDb方法.

namespace Samtt\src; 
use \Resque;
class MoHandler {


    public $db; 
    public $resque; 
    private function getAuthToken($input){
        $arg = json_encode($input);
        return `./registermo $arg`;
    }

    public function setDatabase(Database $db) {
        $this->db = $db; 
    }

    public function setResque($resque) {
        $this->resque = $resque;
    }

    public function save($stackContents){

        if( !is_array($stackContent) || count($stackContents) == 0 )
            return false; 

        $this->db->query("INSERT INTO 
            `mo` (msisdn, operatorid, shortcodeid, text, auth_token, created_at)
             VALUES (:msisdn, :operatorid, :shortcodeid, :text , :auth_token, NOW())"
        );
        $this->db->beginTransaction();
        foreach($stackContents as $item) {

            $auth_token = $this->getAuthToken($stackContents);
            $this->db->bind(':msisdn', $item['msisdn']); 
            $this->db->bind(':operatorid', $item['operatorid']); 
            $this->db->bind(':shortcodeid', $item['shortcodeid']); 
            $this->db->bind(':text', $item['text']); 
            $this->db->bind(':auth_token', $auth_token); 
            $this->db->execute();
        }
        $this->db->endTransaction();

        echo 'A new job stack has been inserted into database ' . PHP_EOL ; 
    }


    /**
     * creating an extra queue in redis is much more efficent than 
     * inserting into mysql for every single request 
     * this function pack data and use batch insert to minimize 
     * database connection
     *  
     * @param  [array] $queueContents [description]
     * @return [boolean] 
     */
    public function createJobStack($input, $queue = null){

        if(! is_array($input)) {
            throw new \InvalidArgumentException;
        }

        // create job stack in redis with "current queue name" 
        // to avoid name collision with possible future job stack

        $stack = $queue .'-jobstack';
        $size  = $this->getSize($stack);
        if($size < Config::$minQueueSize) {

            // check incoming MO and if they are buggy 
            // don't let them pass !
            if(! Validator::validate($input, Config::$validKeys)) {
                echo 'buggy MO' . PHP_EOL ; 
                return false; 
            }

            $this->resque->push($stack, $input);
            echo 'new item has been added to ' . $stack . PHP_EOL; 
            echo 'current stack size is : ' . $size . PHP_EOL; 

        }else {

            $stackContents = [];
            for($i = 1; $i <= Config::$minQueueSize; $i++){
                array_push($stackContents, $this->resque->pop($stack));
            }

            // save the stack into database 
            $this->save($stackContents);
        }

        return true;

    }


    public function getSize($stack) {
        return $this->resque->size($stack);
    }


    public function setUp() {

        $this->setDatabase((new Database));
        $this->setResque((new Resque));

    }
    public function perform(){
        $this->createJobStack($this->args, $this->queue);
    }
}

我编辑并添加了整个班级.我需要多少断言?

最佳答案 这里有一个测试用例,用于检查错误的输入数据,第二个测试用正确的数据.在第二个场景中,我们测试了正确的方法调用,并使用正确的数据调用了bind方法的示例.

<?php


namespace Samtt\src\Tests; 



use Samtt\src\MoHandler;

class MoHandlerTest extends \PHPUnit_Framework_TestCase {

    protected $database;

    protected $handler;

    public function setUp()
    {
        $this->database = $this->getMock('Samtt\src\Database',array('query','beginTransaction','bind','execute','endTransaction'));
        $this->handler = new MoHandler();
        $this->handler->setDatabase($this->database);
    }

    public function test_save_with_invalid_data()
    {
        $input = array();

        $this->database
            ->expects($this->never())
            ->method('query')
        ;

        $this->assertFalse($this->handler->save($input)); // Check te return value
    }

    public function test_save_with_correct_data()
    {
        $input = array(
            array(
            'msisdn' => 'msisdn',
            'operatorid' => 'operatorid',
                'shortcodeid' =>'shortcodeid',
                'text' =>'text'
            )
        );

        $this->database
            ->expects ($this->exactly(5))->method('bind')->withAnyParameters();

        $this->database
            ->expects($this->at(2))
            ->method('bind')
            ->with(':msisdn','msisdn')
        ;

        $this->database
            ->expects($this->once())
            ->method('query')
        ;
        $this->assertNull($this->handler->save($input)); // Check te return value
    }

}

希望这有帮助

进一步参考:

http://www.andrejfarkas.com/2012/07/phpunit-at-method-to-check-method-invocation-at-certain-index/

点赞