我正在使用Symfony,正在尝试在“ Student”类中测试addStudentCard函数,该函数向$ studentCards数组集合专有性中添加了一个“ StudentCard”对象,并向“ StudentCard”中的$ student专有性中添加了一个“ 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类的对象相同。
答案 0 :(得分:0)
您的方案存在的问题是,您断言该模拟返回了原始学生:
$student->assertSame($student, $studentCard->getStudent());
如果$studentCard
是Mock对象,除非您告诉它返回原始对象,否则它不会返回。但是,由于您已经在使用模拟,因此无需测试。
在这种情况下,您实际要测试的是将$student
分配回了$studentCard
。这就是expectations的目的。
因此,在您的特定情况下,您可以选择:
$studentCard->expects($this->once())->method('setStudent')->with($student);
// ...
$student->addStudentCard($studentCard);
在致电addStudentCard
之前,请确保已在那行(如代码中所示),否则测试将失败,即未达到期望。
设置期望值后,无需在模拟对象上运行任何断言(并且不应这样做)。
答案 1 :(得分:0)
提供的答案 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。
希望这对希望做类似事情的人有所帮助。