Skip to content
Snippets Groups Projects
Commit 1ed96922 authored by Alexey Korepov's avatar Alexey Korepov
Browse files

Issue #3315119 by Murz: Implement a getter for mocked method in MockObject

parent 0b576c50
Branches
Tags
1 merge request!12Issue #3315119: Implement a getter for mocked method in MockObject
......@@ -12,6 +12,8 @@ use Drupal\Core\Entity\Query\ConditionInterface as EntityQueryConditionInterface
use Drupal\test_helpers\Stub\ModuleHandlerStub;
use Drupal\test_helpers\Stub\TokenStub;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\MockObject\Builder\InvocationMocker;
use PHPUnit\Framework\MockObject\MethodNameNotConfiguredException;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\Yaml\Yaml;
......@@ -63,6 +65,32 @@ class UnitTestHelpers {
return $property->getValue($class);
}
/**
* Gets a mocked method from the Mock object to replace return value.
*
* This allows to replace the return value of the already defined method via
* `$mockedMethod->willReturn('New Value')`.
*
* It's not possible with PHPUnit API, but here is a feature request about it:
* https://github.com/sebastianbergmann/phpunit/issues/5070 - please vote!
*/
public static function getMockedMethod(MockObject $mock, string $method) {
$invocationHandler = $mock->__phpunit_getInvocationHandler();
$configurableMethods = self::getProtectedProperty($invocationHandler, 'configurableMethods');
$matchers = self::getProtectedProperty($invocationHandler, 'matchers');
foreach ($matchers as $matcher) {
$methodNameRuleObject = self::getProtectedProperty($matcher, 'methodNameRule');
if ($methodNameRuleObject->matchesName($method)) {
return new InvocationMocker(
$invocationHandler,
$matcher,
...$configurableMethods
);
}
}
throw new MethodNameNotConfiguredException();
}
/**
* Parses the annotation for a class and gets the definition.
*/
......
<?php
namespace Drupal\Tests\test_helpers\Unit;
use Drupal\Core\Entity\EntityInterface;
use Drupal\test_helpers\UnitTestHelpers;
use Drupal\Tests\UnitTestCase;
use PHPUnit\Framework\MockObject\MethodNameAlreadyConfiguredException;
/**
* Tests UnitTestHelpers functions.
*
* @coversDefaultClass \Drupal\test_helpers\UnitTestHelpers
* @group test_helpers
*/
class UnitTestHelpersTest extends UnitTestCase {
/**
* @covers ::getMockedMethod
*/
public function testGetMockedMethod() {
$mock = $this->createMock(EntityInterface::class);
$mock->method('label')->willReturn('foo');
$mock->method('id')->willReturn('42');
$this->assertEquals('foo', $mock->label());
// Ensuring that default overriding is not yet available.
try {
$mock->method('label')->willReturn('bar');
}
catch (MethodNameAlreadyConfiguredException $e) {
$this->assertInstanceOf(MethodNameAlreadyConfiguredException::class, $e);
}
$this->assertNotEquals('bar', $mock->label());
// Testing custom overriding of the method return value.
$labelMethod = UnitTestHelpers::getMockedMethod($mock, 'label');
$labelMethod->willReturn('baz');
$mock->method('uuid')->willReturn('myUUID');
$this->assertEquals('baz', $mock->label());
$this->assertNotEquals('foo', $mock->label());
$this->assertEquals('42', $mock->id());
$this->assertEquals('myUUID', $mock->uuid());
// Testing the second overriding of the method return value.
$labelMethod->willReturn('qux');
$this->assertEquals('qux', $mock->label());
// Testing a next getter and overriding of the method return value.
$labelMethod2 = UnitTestHelpers::getMockedMethod($mock, 'label');
$labelMethod2->willReturnArgument(1);
$this->assertEquals('arg1', $mock->label('arg0', 'arg1'));
// Testing a getter with callback function
$idMethod = UnitTestHelpers::getMockedMethod($mock, 'id');
$idMethod->willReturnCallback(function () {
return 777;
});
$this->assertSame(777, $mock->id());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment