Skip to content

Commit 2f5c82b

Browse files
authored
Fix AggregateTypeResolver to respect interface, improve test coverage (#308)
* Fix AggregateTypeResolver to respect interface, improve test coverage * Shift around where exception expectation is declared
1 parent 1d25fd5 commit 2f5c82b

6 files changed

Lines changed: 90 additions & 5 deletions

File tree

src/MapAggregateTypeResolver.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ public function __construct(array $map)
3434

3535
public function resolve(object $aggregate): AggregateType
3636
{
37-
$aggregateType = $this->map[$aggregate::class] ?? null;
38-
\assert($aggregateType instanceof AggregateType);
39-
40-
return $aggregateType;
37+
return $this->map[$aggregate::class] ?? throw CannotResolveAggregateType::of($aggregate, 'Class is not mapped');
4138
}
4239
}

tests/helper/.gitkeep

Whitespace-only changes.

tests/unit/.gitkeep

Whitespace-only changes.

tests/unit/AggregateVersionTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ public function it_throws_when_constructing_from_integer_less_than_one(int $less
4949
*/
5050
public function it_can_provide_the_next_aggregate_version_that_follows_it(): void
5151
{
52-
$this->assertSame(2, AggregateVersion::fromInteger(1)->next()->toInteger());
52+
$v1 = AggregateVersion::fromInteger(1);
53+
$this->assertSame(2, $v1->next()->toInteger());
54+
$this->assertSame(1, $v1->toInteger());
5355
}
5456

5557
/**

tests/unit/ClosureAggregateIdExtractorTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Lendable\Aggregate\AggregateId;
88
use Lendable\Aggregate\AggregateIdExtractor;
9+
use Lendable\Aggregate\CannotExtractAggregateId;
910
use Lendable\Aggregate\ClosureAggregateIdExtractor;
1011
use Lendable\Aggregate\Testing\AggregateIdExtractorSpec;
1112
use Tests\Fixture\Lendable\Aggregate\Blog\Domain\Email;
@@ -36,4 +37,46 @@ protected function createAggregateWithExpectedAggregateId(): object
3637
Email::fromString('foo@example.com')
3738
);
3839
}
40+
41+
/**
42+
* @test
43+
*/
44+
public function it_rethrows_any_interface_compliant_exception_from_the_closure(): void
45+
{
46+
$aggregate = new class () {
47+
};
48+
$exception = CannotExtractAggregateId::from($aggregate);
49+
50+
$extractor = new ClosureAggregateIdExtractor(static function (object $aggregate) use ($exception): AggregateId {
51+
throw $exception;
52+
});
53+
54+
$this->expectExceptionObject($exception);
55+
56+
$extractor->extract($aggregate);
57+
}
58+
59+
/**
60+
* @test
61+
*/
62+
public function it_wraps_and_throws_for_any_non_interface_compliant_exception_from_the_closure(): void
63+
{
64+
$aggregate = new class () {
65+
};
66+
$exception = new \Exception();
67+
68+
$extractor = new ClosureAggregateIdExtractor(static function (object $aggregate) use ($exception): AggregateId {
69+
throw $exception;
70+
});
71+
$wasAnExceptionThrown = false;
72+
73+
try {
74+
$extractor->extract($aggregate);
75+
} catch (CannotExtractAggregateId $thrown) {
76+
$wasAnExceptionThrown = true;
77+
$this->assertSame($exception, $thrown->getPrevious());
78+
}
79+
80+
$this->assertTrue($wasAnExceptionThrown);
81+
}
3982
}

tests/unit/MapAggregateTypeResolverTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Tests\Unit\Lendable\Aggregate;
66

77
use Lendable\Aggregate\AggregateType;
8+
use Lendable\Aggregate\CannotResolveAggregateType;
89
use Lendable\Aggregate\MapAggregateTypeResolver;
910
use PHPUnit\Framework\TestCase;
1011

@@ -22,4 +23,46 @@ public function it_can_resolve_an_aggregate_type_for_a_mapped_aggregate_root():
2223

2324
$this->assertSame('foo', $fixture->resolve(new \stdClass())->toString());
2425
}
26+
27+
/**
28+
* @test
29+
*/
30+
public function it_throws_if_a_mapped_class_does_not_exist(): void
31+
{
32+
$this->expectException(\InvalidArgumentException::class);
33+
$this->expectExceptionMessage('All map keys must be class names that exist, FooBarBaz does not exist.');
34+
35+
// @phpstan-ignore-next-line intentional undefined class.
36+
new MapAggregateTypeResolver([\FooBarBaz::class => AggregateType::fromString('FooBarBaz')]);
37+
}
38+
39+
/**
40+
* @test
41+
*/
42+
public function it_throws_if_a_mapped_value_is_not_an_aggregate_type(): void
43+
{
44+
$badValue = new class () {
45+
};
46+
47+
$this->expectException(\InvalidArgumentException::class);
48+
$this->expectExceptionMessage(\sprintf('All map values must be instances of %s, %s is not', AggregateType::class, $badValue::class));
49+
50+
// @phpstan-ignore-next-line intentionally non-compliant value passed.
51+
new MapAggregateTypeResolver([\stdClass::class => $badValue]);
52+
}
53+
54+
/**
55+
* @test
56+
*/
57+
public function it_throws_if_cannot_resolve_an_aggregate_as_not_mapped(): void
58+
{
59+
$this->expectException(CannotResolveAggregateType::class);
60+
61+
$fixture = new MapAggregateTypeResolver([\stdClass::class => AggregateType::fromString('foo')]);
62+
$fixture->resolve(
63+
// @phpstan-ignore-next-line intentional bad method call violating static analysis for runtime check.
64+
new class () {
65+
}
66+
);
67+
}
2568
}

0 commit comments

Comments
 (0)