PHPUnit:测试对象数组

时间:2013-06-24 14:40:46

标签: php unit-testing phpunit

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

我需要测试这个场景,我有Student Class,就像这样:

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检查值

请把一些灯光/信息/链接扔到正确的路径上。

由于

3 个答案:

答案 0 :(得分:29)

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

class StudentsTest extends PHPUnit_Framework_TestCase{

    public function testGetAllStudents(){
        $s=new Students;
        $students=$s->getStudents("","");
        $this->assertInternalType('array',$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->assertInternalType('array',$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从数据库获取数据,那么它也会很慢;我们希望单元测试能够尽快运行。

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

究竟如何进行模拟是一个完整的问题,可能依赖于PHP版本,以及代码设置的灵活性。 (“OldStudents”听起来像是在处理遗留代码,也许你无法触及它。)

答案 1 :(得分:21)

PHPUnit,因为3.1.4版本的断言“assertContainsOnly”带有参数“type”,它可以断言任何PHP类型(包括实例和内部类型),并且至少版本3.7中有断言“assertContainsOnlyInstancesOf”,它只明确地显示检查类实例,而不是PHP变量类型。

因此测试检查数组是否只包含给定类型的对象只是:

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

请注意,此检查隐式测试$students是实现Traversable接口的数组还是对象。实现Traversable并不意味着你可以计数,所以之后调用assertCount来断言给定数量的Student对象并不能保证成功,但是添加的检查确实返回值实际上是一个数组这里对我来说似乎太臃肿了。您正在创建并返回包含其中某些内容的数组 - 可以安全地假设您可以计算它。但到处都不是这种情况。

答案 2 :(得分:3)

你可以用断言来做到这一点。首先,您应该获取实际结果,然后对其进行一些断言。比较:

你可以断言它是一个数组:

class InternalTypeTest extends PHPUnit_Framework_TestCase
{
    public function testFailure()
    {
        $this->assertInternalType('array', 42);
        # Phpunit 7.5+: $this->assertIsArray(42);
    }
}

然后你可以断言它不是空的(因为你知道它必须返回一些数据):

class NotEmptyTest extends PHPUnit_Framework_TestCase
{
    public function testFailure()
    {
        $this->assertNotEmpty(ARRAY());
    }
}

然后你可以断言每个值都是你的学生类型:

class InstanceOfTest extends PHPUnit_Framework_TestCase
{
    public function testFailure()
    {
        $this->assertInstanceOf('Student', new Exception);
    }
}

我希望这会给你一些指示。请参阅上面的链接以获取常见断言的列表。如果您使用IDE来测试它,它应该提供所有断言的列表。