PHPUnit:测试对象数组

125*_*369 14 php phpunit unit-testing

刚刚跳进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;
    }
}
Run Code Online (Sandbox Code Playgroud)

和学生班

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;
    }   
}
Run Code Online (Sandbox Code Playgroud)

现在,我如何测试Students Class 是否返回一组具有设置值的对象,并使用Student Class中的getter检查值

请抛出一些灯光/信息/链接,无论哪个指引我在正确的路径.

谢谢

Dar*_*ook 33

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

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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


Sve*_*ven 24

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

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

$this->assertContainsOnlyInstancesOf('Student', $students);
Run Code Online (Sandbox Code Playgroud)

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


hak*_*kre 5

你可以用断言来做到这一点。首先你应该得到一个实际的结果,然后用它做一些断言。相比:

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

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

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

class NotEmptyTest extends PHPUnit_Framework_TestCase
{
    public function testFailure()
    {
        $this->assertNotEmpty(ARRAY());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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