在下面的代码中,我应该如何编写单元测试?
我该如何模拟数据库?嘲笑有什么意义?想象一下,在同一个保存类中,我们有一个注入数据库依赖的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/