Php 您将如何测试这种典型的控制器方法?
我正在使用PHPUnit测试我的MVC应用程序。我的模型的大部分代码(本例中的Site、MStudent、MMenu)都包含了单元测试,但我发现很难在控制器上测试功能。我的框架中的典型控制器功能如下所示:Php 您将如何测试这种典型的控制器方法?,php,unit-testing,model-view-controller,phpunit,Php,Unit Testing,Model View Controller,Phpunit,我正在使用PHPUnit测试我的MVC应用程序。我的模型的大部分代码(本例中的Site、MStudent、MMenu)都包含了单元测试,但我发现很难在控制器上测试功能。我的框架中的典型控制器功能如下所示: /** * List the mentor's students */ public function students() { // set some variables needed in the view $menu = MMenu::init($this->m
/**
* List the mentor's students
*/
public function students()
{
// set some variables needed in the view
$menu = MMenu::init($this->mentor, "List of students");
$filter = "";
$students = array();
$sql = "SELECT * "
. "FROM {Site::app()->settings['tablePrefix']}students s "
. "WHERE s.pID = {$this->mentor->id} "
. "ORDER BY s.lastvisit DESC";
$cmd = Site::app()->db()->prepare($sql);
if ($cmd->execute() AND ($rows = $cmd->fetchAll(PDO::FETCH_ASSOC)))
{
foreach ($rows as $row)
{
$students[] = new MStudent($row);
}
}
// call the view
include Site::app()->viewPath("manage/students");
exit;
}
里面有什么可以测试的东西吗?你将如何测试它
编辑:因此,根据Stephen的反馈,我可以重构并将数据库访问放在模型中:
public function students()
{
// set some variables needed in the view
$menu = MMenu::init($this->mentor, "List of students");
$filter = "";
$students = MStudent::studentsFromQuery("SELECT * FROM students WHERE pID=" . $this->mentor->id);
// call the view
include Site::app()->viewPath("manage/students");
exit;
}
现在这里要测试的东西更少了。测试这样的功能有意义吗?如何做?应该注意,将控制器逻辑移动到模型中并不排除在控制器测试中测试它的需要!你进入模型的任何东西都会被嘲笑
很少有一个控制器能够以一种值得的方式进行单元测试(IMO)。模拟所有依赖项的成本/收益并没有得到回报。通常,控制器方法会作为系统测试的一部分进行间接测试。如果这是MVC,那么我认为您的控制器有点胖。确定数据库访问应该在模型中吗?是的,数据库查询肯定应该在模型中。我会将整个查询放入模型中,以从控制器中抽象出所有SQL。在
MStudent
上创建一个方法,例如studentsformontor($menterid)
。此外,使用静态方法测试代码也会很困难。调用exit
也是测试的杀手。至少把它放在基本控制器中的doExit()
方法中,您可以在测试期间模拟或禁用它。看来SO社区中没有人有更好的答案,所以我接受您的方法。谢谢你的回答。它澄清了困扰我很久的一些事情。