在下面的代码中,我应该如何编写单元测试? 我该如何模拟数据库?嘲笑有什么意义?想象一下,在同一个保存类中,我们有一个注入数据库依赖的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);
}
}
我编辑并添加了整个班级。我需要多少断言?
答案 0 :(得分:2)
这是一个用错误输入数据检查的测试用例和带有正确数据的第二次测试。在第二个场景中,我们测试了正确的方法调用,并使用正确的数据调用了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/