How would you test this typical controller method?
I'm using PHPUnit to test my MVC application. Most of the code for my models (Site, MStudent, MMenu in this example) are well covered with unit tests, but I find it difficult to test the functions on my controllers. A typical controller function in my framework looks like this:
/**
* List the mentor's stude开发者_StackOverflownts
*/
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;
}
Is there something senseable to test in there? How would you test it?
EDIT:
So from Stephen's feedback, I can refactor and put the database access in the model: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;
}
Now there is even less to test here. Does it make sense to test functions like these and how would one do it?
It should be noted that moving controller logic into the models does not preclude the need to test it in your controller tests! Whatever you move into the models will have to be mocked.
It's rare to have a controller that does so little that it can actually be unit tested in a way that makes it worthwhile (IMO). The cost/benefit to mocking all of the dependencies just doesn't pay off. Often controller methods are instead tested indirectly as part of system tests.
精彩评论