2

I am doing some unit testing with PHP. I got stuck on an error that the fluent interface of PHPUnit requires an intermediate variable. What is the reason for this behavior?

See MyTests::works vs. MyTests::fails:

<?php use PHPUnit\Framework\TestCase; interface SomeInterface { public function someMethod(); } class SomeService { public function __construct( private SomeInterface $interface ) { } public function testMethod() { $this->interface->someMethod(); } } class MyTests extends TestCase { // Using fluent-interface with intermediate variable works public function works() { $mock = $this->createMock(SomeInterface::class); $mock->expects($this->once()) ->method("someMethod"); $service = new SomeService($mock); $service->testMethod(); } // Using fluent-interface without intermediate variable fails public function fails() { // Fails: TypeError: SomeService::__construct(): Argument #1 ($interface) must be of type SomeInterface, PHPUnit\Framework\MockObject\InvocationStubberImplementation given, called in /xxx/MyTests.php on line 25 $mock = $this->createMock(SomeInterface::class) ->expects($this->once()) ->method("someMethod"); $service = new SomeService($mock); $service->testMethod(); } } ?> 

I already found the same question asked before (Mock class with fluent interface in Phpunit), but I am searching for the why not for the fix.

1 Answer 1

5

createMock returns a MockObject. But expects and method return an InvocationStubber.

So for the fluent interface chain

$variable = $this->createMock(...)->expects(...)->method(...) 

the return types change in-flight and only the return value of the last call in the chain gets stored in the variable assignment.

By preserving the return value of createMock(...) in an extra variable one prevents the type error, since only the MockObject provides the "type magic" required.

So it's just some suprising design of the fluent interface from my point of view, not a PHP-specific behavior.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.