首页 > 解决方案 > PHPunit:如何从外部函数更改 Mock 对象的属性

问题描述

我正在使用 Symfony,并且正在尝试测试“Student”类中的 addStudentCard 函数,该函数将“StudentCard”对象添加到 $studentCards 数组集合属性中,并将“Student”对象添加到“StudentCard”类中的 $student 属性中。我是这样做的:

class StudentCard {
  private $student;
  public function getStudent();
  public function setStudent();
  //...
}

class Student {
  private $studentCards;
  public function getStudentCards();
  public function addStudentCard(StudentCard $studentCard){
    $studentCard->setStudent($this);
    $this->studentCards[] = $studentCard;
    return $this;
  //...
}

我想要实现的是使用 MockBuilder 测试这个 addStudentCard 函数,我已经通过以下方式在不使用模拟的情况下完成了这项工作:

class StudentTest extends AbstractTestCase {
  public function testAddStudentCard(){
    $studentCard = new StudentCard();
    $student = new Student();
    $student->addStudentCard($studentCard);
    $student->assertSame($studentCard, $student->getStudentCards()[0]);
    $student->assertSame($student, $studentCard->getStudent());
}

这可以按预期工作,没有问题。

我想要的是替换该行:

$studentCard = new StudentCard();

像这样:

$studentCard = $this->getMockBuilder(StudentCard::class)->getMock();

但我得到的是错误:断言 null 与 Student 类的对象相同失败。

标签: phpsymfonyphpunit

解决方案


Ondrej Führer提供的答案是我描述的问题的正确答案
我还有一个 removeStudentCard 方法,可以从 studentCard 对象中删除学生,所以 $this->once() 不适合我的情况。为了测试这一点,我做了与Ondrej Führer建议的完全相同的事情,但做了一些修改,所以我添加的代码行是:

$studentCard->expects($this->exactly(2))->method('setStudent')->withConsecutive(
    [$student],
    [null]
);
//...
$student->addStudentCard($studentCard);
//...
$student->removeStudentCard($studentCard);

这是自我解释,方法 setContact 预计将被调用两次,第一次以 $student 作为参数,第二次调用为 null。
希望这对任何想要做类似事情的人有所帮助。


推荐阅读