@HellWalk

PHPUNIT: Как возвращать разные значения в методе мока?

Официальная документация указывает следующий вариант:

$stub = $this->createMock(SomeClass::class);

// Настроить заглушку.
$stub->method('doSomething')
      ->will($this->onConsecutiveCalls(2, 3, 5, 7));

// Вызов $stub->doSomething() вернёт разное значение каждый раз
$this->assertSame(2, $stub->doSomething());
$this->assertSame(3, $stub->doSomething());
$this->assertSame(5, $stub->doSomething());


Но, в моем случае это не работает - т.к. указана типизация:

$mock->method('handle')->willReturn($this->onConsecutiveCalls($response1, $response2));

ERROR: Method handle may not return value of type PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls, its
return declaration is ": ...\ResponseInterface"


Вроде бы элементарная задача, но вожусь уже несколько часов с документацией и исходниками.
  • Вопрос задан
  • 483 просмотра
Решения вопроса 1
Maksclub
@Maksclub Куратор тега PHP
maksfedorov.ru
Так точно работает:
$this->anyMock
    ->expects($this->exactly(4))
    ->method('doSomething')
    ->withConsecutive(...$args)
    ->willReturnOnConsecutiveCalls(...$results)

Кол-во $args и $results и цифра в $this->exactly(4) одинаково,
$args - массив массивов


UPD: Сейчас глянул код, по идее ваш способ абсолютно эквивалентный и должен работать, либо приведенный мной будет ругаться также. переменные $response1 и $response2 точно имплементят ResponseInterface?

Причина проблемы:
Вы просто настраиваете мок на одно число вызовов, а в ассертах вызываете меньшее число раз (в примере -- настроили на 4 ответа, а ассертов всего 3, то есть 1 остался заряженный) и в моке остается значение, которое потом вызывается каким-либо образом в других ситцациях!
Классический сайд эффект. Нужно после использованного мока удостовериться, что он пустой или в новом тесте заново его создать, скорее всего у вас мок в приватной переменной класса и потому состояние шарится между методами теста...

Именно поэтому вам expects() скорее всего и подсказала, в чем дело.

Решения:
  1. Создавать мок именно в методе, не злобоупотреблять setUp()
  2. Контроллировать число вызовов в методе и аргументов для Consecutive Calls, в этом поможет expects($this->exactly(N))
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@nyatmeat15
Еще можно возвращать willReturnCallback(function(){
$arguments = func_get_args(); //получить аргументы функции и что-то с ними сделать
})

Как правило можно так задать поведение функции
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы