H
H
HellWalk2020-04-29 14:27:43
PHP
HellWalk, 2020-04-29 14:27:43

PHPUNIT: How to return different values ​​in mock method?

The official documentation specifies the following option:

$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());


But, in my case, this does not work - because. typing specified:

$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"


It seems to be an elementary task, but I've been fiddling with the documentation and source codes for several hours.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
M
Maksim Fedorov, 2020-04-29
@HellWalk

This is exactly how it works:

$this->anyMock
    ->expects($this->exactly(4))
    ->method('doSomething')
    ->withConsecutive(...$args)
    ->willReturnOnConsecutiveCalls(...$results)

The number of $args and $results and the number in $this->exactly(4) are the same,
$args is an array of arrays

UPD: Now I looked at the code, in theory your method is absolutely equivalent and should work, or the one I have given will swear as well. variables $response1 and $response2 exactly implement ResponseInterface?
Cause of the problem:
You simply set the mock to one number of calls, and in the asserts you call fewer times (in the example, you set it to 4 answers, and there are only 3 asserts, that is, 1 remained charged) and the value remains in the mock, which is then called by what -either way in other sitsations!
Classic side effect. After the used mock, you need to make sure that it is empty or re-create it in a new test, most likely you have a mock in a private class variable and therefore the state is rummaged between the test methods ...
That is why expects() most likely told you what was the matter .
Solutions:
  1. Create a mock in the method, do not abuse setUp ()
  2. Control the number of calls in the method and arguments for Consecutive Calls, this will helpexpects($this->exactly(N))

N
nyatmeat15, 2020-11-14
@nyatmeat15

You can also return willReturnCallback(function(){
$arguments = func_get_args(); // get the function arguments and do something with them
})
As a rule, you can set the behavior of the function like this

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question