PHPunit: Как изменить свойство Mock-объекта из внешней функции - PullRequest
0 голосов
/ 28 мая 2019

Я использую Symfony и пытаюсь протестировать функцию addStudentCard в классе "Student", которая добавляет объект "StudentCard" к собственности коллекции массивов $ studentCards И объект "Student" к собственности $ student в "StudentCard" учебный класс. Вот как я это сделал:

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;
  //...
}

Чего я хочу добиться, так это протестировать эту функцию addStudentCard с помощью MockBuilder, я уже сделал это без использования макетов, выполнив:

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.

Ответы [ 2 ]

0 голосов
/ 29 мая 2019

Ответ Ондрей Фюрер дает правильный ответ на проблему, которую я описал.
У меня был также метод removeStudentCard, который удаляет студента изобъект studentCard, поэтому $ this-> once () не подходит для моего случая.Чтобы проверить это, я сделал то же самое, что Ондрей Фюрер предложил с некоторыми изменениями, поэтому строка кода, которую я добавил, была:

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

ЭтоСамо собой разумеется, ожидается, что метод setContact будет вызываться exaclty два раза с аргументом $ student в первый раз и нулевым во втором вызове.
Надеюсь, это будет полезно для любого, кто хочет сделать что-то подобное.

0 голосов
/ 28 мая 2019

Проблема с вашим сценарием в том, что вы утверждаете, что макет возвращает оригинального ученика:

$student->assertSame($student, $studentCard->getStudent());

Если $studentCard является объектом симуляции, он не возвращает исходный объект, если толькоВы говорите это сделать.Но так как вы уже используете макет, проверять это не нужно.

Что вы действительно хотите проверить в этом случае, так это то, что $student был присвоен обратно $studentCard.Вот для чего ожидания .

Итак, в вашем конкретном случае вы бы использовали:

$studentCard->expects($this->once())->method('setStudent')->with($student);
// ...
$student->addStudentCard($studentCard);

Убедитесь, что у вас есть линия (как я показалв коде) перед вызовом addStudentCard, иначе тест не будет выполнен, если ожидание не было выполнено.

После того, как вы установите ожидания, нет необходимости запускать какие-либо утверждения (и вы не должны)на макет объектов.

...