ci_phpunit_test:有关查询的测试加倍需要帮助

时间:2016-06-30 10:15:20

标签: php mysql codeigniter unit-testing

我正在学习使用CodeIgniter进行单元测试,我会问一些关于使用Mocks类测试查询的问题。

我尝试使用方法get_news_all()实现以下类News_model,该方法返回表'news'中的所有新闻数据,get_news仅返回标题和文本字段。

class News_model extends CI_Model
{
public function __construct(){
    $this->load->database();
}

public function get_news_all()
{
    $query=$this->db->get('news');
    $result=$query->result_array();
    return $result;
}

public function get_news()
{
    $this->db->select('title, text');
    $this->db->from('news');
    $query=$this->db->get();
    $result=$query->result_array();
    return $result;
}

在我尝试为测试方法get_news_all()构建News_model_with_mocks_test之后,在这种情况下测试运行正常:

class News_model_with_mocks_test extends TestCase
{
public function setUp()
{
    $this->resetInstance();
    $loader=$this->getMockBuilder('CI_Loader')->setMethods(['database'])->getMock();
    $loader->method('database')->willReturn($loader);
    $this->CI->load=$loader;
    if(!class_exists('CI_DB', false))
    {
        eval('class CI_DB extends CI_DB_query_builder {}');
    }
    $this->obj=new News_model();
}

public function test_1()
{
    $result_array = [
            [
                    "id" => "1",
                    "title" => "News",
                    "slug" => "news",
                    "text" => "News",
            ],
            [
                    "id" => "2",
                    "title" => "News2",
                    "slug" => "news2",
                    "text" => "News2",
            ],
    ];
    $db_result=$this->getMockBuilder('CI_DB_result')->disableOriginalConstructor()->getMock();
    $db_result->method('result_array')->willReturn($result_array);
    $db = $this->getMockBuilder('CI_DB')->disableOriginalConstructor()->getMock();
    $db->expects($this->once())->method('get')->with('news')->willReturn($db_result);
    $this->obj->db=$db;
    $result=$this->obj->get_news_all();
    $this->assertEquals($result_array,$result);
}

}

但是我不知道如何为方法get_news()做测试,我尝试了这样的事情:

public function test_1()
{
    $result_array2 = [
            [
                    "title" => "News",
                    "text" => "News",
            ],
            [
                    "title" => "News2",
                    "text" => "News2",
            ],
    ];
    $db_result=$this->getMockBuilder('CI_DB_result')->disableOriginalConstructor()->getMock();
    $db_result->method('result_array')->willReturn($result_array2);
    $db = $this->getMockBuilder('CI_DB')->disableOriginalConstructor()->getMock();
    $db->expects($this->once())->method('query')->with('select title,text from news')->willReturn($db_result);
    $this->obj->db=$db;
    $result=$this->obj->get_news();
    $this->assertEquals($result_array2,$result);
}

phpunit引发以下异常:

PHP Fatal error:  Call to a member function result_array() on a non-   object in /opt/lampp/htdocs/codeigniter/application/models/Users_model.php on line 21

我不知道如何使用select查询测试双倍!提前感谢您的回答。

1 个答案:

答案 0 :(得分:0)

我在这些日子里阅读了更多文档,我明白这是对我使用Mocks的一个误解。换句话说,我们必须定义方法并返回我们期望的值并将它们注入原始类。这是我在上面写的类News_model的方法get_users:

public function get_news()
{
    $this->db->select('title, text');
    $this->db->from('news');
    $query=$this->db->get();
    $result=$query->result_array();
    return $result;
}

我们只是想让get()方法返回一个结果数组,该数组只包含每条记录的标题和文本字段:

class News_model_with_mocks_test extends TestCase
{
public function setUp()
{
    $this->resetInstance();
    $loader=$this->getMockBuilder('CI_Loader')->setMethods(['database'])->getMock();
    $loader->method('database')->willReturn($loader);
    $this->CI->load=$loader;
    if(!class_exists('CI_DB', false))
    {
        eval('class CI_DB extends CI_DB_query_builder {}');
    }
    $this->obj=new News_model();
} 

public function test_1()
{
    $result_array = [
            [
                    "title" => "News test",
                    "text" => "News text",
            ],
            [
                    "title" => "News2",
                    "text" => "Testo news2",
            ],
    ];
    $db_result=$this->getMockBuilder('CI_DB_result')->disableOriginalConstructor()->getMock();
    $db_result->method('result_array')->willReturn($result_array);
    $db = $this->getMockBuilder('CI_DB')->disableOriginalConstructor()->getMock();
    $db->expects($this->once())->method('get')->willReturn($db_result);
    $this->obj->db=$db;
    $result=$this->obj->get_news();
    $this->assertEquals($result_array,$result);
}
}

我希望这个解决方案可以帮助那些有同样疑虑的人!