PHPUnit:对象的测试数组

2022-08-30 22:35:04

最近刚进入PHPUnit,一直在阅读有关它的东西,尝试一些例子,以便为我未来的项目编写测试。

我需要测试这个场景,我有学生班,它是这样的:

class Students
{
    public function getStudents($studentName, $studentId)
    {       
        $students= array();

        //Instantiating OldStudent Class from Old Project
        $oldStudents = \OldStudents::getStudentByName($studentName, $studentId);

        //Create a Student Object for every OldStudent found on Old Project and set
        //values
        foreach ($oldStudents as $oldStudent)
        {            
            $student = new \Entity\Student();

            //Set Student ID
            $student->setStudentId($oldStudent->getStudentID());

            //Set Student Name
            $student->setStudentName($oldStudent->getStudentName());    
           //.....other setters for student data, irrelevant for this example 

            $students[] = $student;            
        }

        return $students;
    }
}

和学生班

Class Student
{
    protected $studentId;
    protected $studentName;

    public function getStudentId()
    {
        return $this->studentId;
    }
    public function setStudentId($studentId)
    {
        $this->studentId = $studentId;
        return $this;
    }
    public function getStudentName()
    {
        return $this->studentName;
    }
    public function setStudentName($studentName)
    {
        $this->studentName = $studentName;
        return $this;
    }   
}

现在,我如何测试学生类是否返回设置了值的对象数组,并检查值是否使用学生类中的 getter

请抛出一些光线/信息/链接,以指引我走上正确的道路。

谢谢


答案 1

我在下面写了一些示例代码;我猜参数是可选过滤器。我们有一个测试,可以吸引所有学生。我不知道他们是否总是按顺序回来,这就是为什么我不在学生课堂上测试其他任何东西。第二个测试获取一个特定的学生,并开始测试一些 Student 属性。getStudents

class StudentsTest extends PHPUnit_Framework_TestCase{

    public function testGetAllStudents(){
        $s=new Students;
        $students=$s->getStudents("","");
        $this->assertIsArray($students);
        $this->assertEquals(7,count($students));
        $first=$students[0];    //Previous assert tells us this is safe
        $this->assertInstanceOf('Student',$first);
    }

    public function testGetOnlyStudentNamedBob(){
        $s=new Students;
        $students=$s->getStudents("Bob","");
        $this->assertIsArray($students);
        $this->assertEquals(1,count($students));
        $first=$students[0];    //Previous assert tells us this is safe
        $this->assertInstanceOf('Student',$first);
        $this->assertEquals('Bob',$first->getStudentName());
    }
}

这是很好的第一步。使用它一段时间后,您会意识到它非常脆弱。也就是说,您必须有正好7名学生才能通过第一次测试。必须正好有一个叫鲍勃的学生才能通过第二个。如果您从数据库中获取数据,它也会很慢;我们希望单元测试尽可能快地运行。\OldStudents::getStudentByName

这两个问题的解决方法是模拟对 的调用。然后,您可以注入自己的人工数据,然后您只需在 中测试逻辑。这反过来意味着,当你的单元测试中断时,只有20行左右的线可以打破它,而不是1000行。\OldStudents::getStudentByNamegetAllStudents

究竟如何进行模拟是一个完整的问题,并且可能取决于PHP版本,以及您的代码设置的灵活性。(“OldStudents”听起来像是你在处理遗留代码,也许你不能碰它。


答案 2

自3.1.4版本以来,PHPUnit具有断言“assertContainsOnly”,参数“type”可以断言任何PHP类型(包括实例和内部类型),并且至少在版本3.7中具有断言“assertContainsOnlyInstancesOf”,它显式仅检查类实例,而不是PHP变量类型。

因此,测试检查数组是否仅包含给定类型的对象很简单:

$this->assertContainsOnlyInstancesOf('Student', $students);

请注意,此检查隐式测试的是实现可遍历接口的数组或对象。实现Traversable并不意味着你可以计数,所以事后调用断言给定数量的对象存在并不能保证成功,但是添加的检查返回值实际上是一个数组对我来说似乎太膨胀了。您正在创建并返回一个包含某些内容的数组 - 可以安全地假设您可以对其进行计数。但这种情况可能并非在所有地方都是如此。$studentsassertCountStudent


推荐