Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kbond committed Jan 8, 2021
1 parent 100d207 commit a08e8e0
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/Callback.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,18 @@ private function replaceArgument(\ReflectionParameter $argument)
$type = $argument->getType();

if (!$type && \array_key_exists(null, $this->typeReplace)) {
return $this->typeReplace[null];
return $this->typeReplace[null] instanceof \Closure ? $this->typeReplace[null]() : $this->typeReplace[null];
}

if (!$type instanceof \ReflectionNamedType) {
throw new \TypeError("Unable to replace argument \"{$argument->getName()}\".");
throw new \TypeError("Unable to replace argument \"{$argument->getName()}\". No replaceUntypedArgument set.");
}

foreach (\array_keys($this->typeReplace) as $typehint) {
if ($type->isBuiltin() && $typehint === $type->getName()) {
return $this->typeReplace[$typehint];
}

if (!\is_a($type->getName(), $typehint, true)) {
continue;
}
Expand Down
157 changes: 157 additions & 0 deletions tests/CallbackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,155 @@
*/
final class CallbackTest extends TestCase
{
/**
* @test
*/
public function can_execute_string_callbacks(): void
{
$actual = Callback::createFor('strtoupper')
->minArguments(1)
->replaceUntypedArgument('foobar')
->execute()
;

$this->assertSame('FOOBAR', $actual);
}

/**
* @test
*/
public function can_execute_closures(): void
{
$actual = Callback::createFor(function($string) { return \mb_strtoupper($string); })
->minArguments(1)
->replaceUntypedArgument('foobar')
->execute()
;

$this->assertSame('FOOBAR', $actual);
}

/**
* @test
*/
public function can_enforce_min_arguments(): void
{
$callback = Callback::createFor(function() { return 'ret'; })
->minArguments(1)
;

$this->expectException(\ArgumentCountError::class);

$callback->execute();
}

/**
* @test
*/
public function can_replace_primitive_typehints(): void
{
$actual = Callback::createFor(function(string $string) { return \mb_strtoupper($string); })
->minArguments(1)
->replaceTypedArgument('string', 'foobar')
->execute()
;

$this->assertSame('FOOBAR', $actual);
}

/**
* @test
*/
public function can_replace_class_argument(): void
{
$object = new Object2();
$function = static function(Object1 $object1, Object2 $object2, $object3) {
return [
'object1' => $object1,
'object2' => $object2,
'object3' => $object3,
];
};

$actual = Callback::createFor($function)
->replaceTypedArgument(Object1::class, $object)
->replaceUntypedArgument($object)
->execute()
;

$this->assertSame(
[
'object1' => $object,
'object2' => $object,
'object3' => $object,
],
$actual
);
}

/**
* @test
*/
public function can_replace_class_typehint_with_factory(): void
{
$function = static function(Object1 $object1, Object2 $object2, $object3) {
return [
'object1' => $object1,
'object2' => $object2,
'object3' => $object3,
];
};
$factoryArgs = [];
$factory = static function($arg = null) use (&$factoryArgs) {
$factoryArgs[] = $arg;

return new Object2();
};

$ret = Callback::createFor($function)
->replaceTypedArgument(Object1::class, $factory)
->replaceUntypedArgument($factory)
->execute()
;

$this->assertSame(['object1', 'object2', 'object3'], \array_keys($ret));
$this->assertInstanceOf(Object2::class, $ret['object1']);
$this->assertInstanceOf(Object2::class, $ret['object2']);
$this->assertInstanceOf(Object2::class, $ret['object3']);
$this->assertSame(
[Object1::class, Object2::class, null],
$factoryArgs
);
}

/**
* @test
*/
public function type_error_thrown_if_no_untyped_argument_defined(): void
{
$callback = Callback::createFor(static function($arg) {});

$this->expectException(\TypeError::class);
$this->expectExceptionMessage('No replaceUntypedArgument set');

$callback->execute();
}

/**
* @test
*/
public function type_error_thrown_if_type_argument_not_defined(): void
{
$callback = Callback::createFor(static function(Object2 $object1) {})
->replaceTypedArgument(\stdClass::class, new \stdClass())
;

$this->expectException(\TypeError::class);
$this->expectExceptionMessage('Unable to replace argument "object1"');

$callback->execute();
}

/**
* @test
*/
Expand All @@ -20,3 +169,11 @@ public function create_must_be_callable(): void
Callback::createFor('not a callable');
}
}

class Object1
{
}

class Object2 extends Object1
{
}

0 comments on commit a08e8e0

Please sign in to comment.