Successfully reported this slideshow.
Your SlideShare is downloading. ×

Testy API: połączenie z bazą danych czy implementacja w pamięci

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 33 Ad

Testy API: połączenie z bazą danych czy implementacja w pamięci

Download to read offline

Testy integracyjne wykonują realne żądania na API. Trzeba zatem zadbać o odpowiednie skonfigurowanie środowiska do testów. Kwestia danych to jedno z podstawowych zagadnień z którym należy sobie poradzić. Do tematu można podejść na kilka sposobów, ale sprowadzają się one do dwóch kategorii: baza danych albo implementacja w pamięci. Dowiedz się, które z nich sprawdzi się w twoim projekcie.

Testy integracyjne wykonują realne żądania na API. Trzeba zatem zadbać o odpowiednie skonfigurowanie środowiska do testów. Kwestia danych to jedno z podstawowych zagadnień z którym należy sobie poradzić. Do tematu można podejść na kilka sposobów, ale sprowadzają się one do dwóch kategorii: baza danych albo implementacja w pamięci. Dowiedz się, które z nich sprawdzi się w twoim projekcie.

Advertisement
Advertisement

More Related Content

More from The Software House (20)

Advertisement

Testy API: połączenie z bazą danych czy implementacja w pamięci

  1. 1. Testy API połączenie z bazą danych czy implementacja w pamięci Krystian Żądło (koddlo.pl)
  2. 2. ● Testy API, czyli co… ● Testowanie kodu wymagającego źródła danych ● Baza danych dla testów ○ Zady i Walety ○ Przykład w PHP ● Implementacja w pamięci ○ Zady i Walety ○ Przykład w PHP ● Porównanie rozwiązań ● Podsumowanie ● Bonus ● Q&A Spis treści
  3. 3. Testy API, czyli co…
  4. 4. Testowanie kodu wymagającego źródła danych
  5. 5. Baza danych dla testów
  6. 6. Zady i Walety + najbardziej zbliżone do produkcji + krótki czas implementacji + łatwy development + łatwe do wprowadzenia w legacy - bardzo wolne i zasobożerne - rzadko uruchamiane
  7. 7. final class UserAPITest extends WebTestCase { private KernelBrowser $client; private UserFixture $fixtures; public function testGivenValidPayloadWhenCreatingUserShouldReturn201(): void {...} public function testGivenNoParametersWhenListingUsersShouldReturn200WithAllUsers(): void {...} protected function setUp(): void {...} } Przykład w PHP
  8. 8. protected function setUp(): void { $this→client = static::createClient(); $this→fixtures = $this→client→getContainer()→get(UserFixture::class); $entityManager = $this→client→getContainer()→get(EntityManagerInterface::class); $metadata = $entityManager→getMetadataFactory()→getAllMetadata(); $schemaTool = new SchemaTool($entityManager); $schemaTool→dropSchema($metadata); $schemaTool→createSchema($metadata); } Przykład w PHP
  9. 9. public function testGivenValidPayloadWhenCreatingUserShouldReturn201(): void { $body = [ 'name' ⇒ 'John Doe', 'email' ⇒ 'john.doe@example.com' ]; $this→client→jsonRequest('POST', 'users', $body); $this→assertResponseStatusCodeSame(Response::HTTP_CREATED); } Przykład w PHP
  10. 10. public function testGivenNoParametersWhenListingUsersShouldReturn200WithAllUsers(): void { $this→fixtures→load(); $expectedContent = ' [ { "id": "4a4e03b2-5acc-4693-9d1f-dbc2d5662ee4", "email": "john.doe@example.com", "name": "John Doe" }, { "id": "3b3e03b2-5acc-4693-9d1f-dbc2d5662ff1", "email": "jane.dawson@example.com", "name": "Jane Dawson" } ] '; $this→client→request('GET', 'users'); $this→assertResponseStatusCodeSame(Response::HTTP_OK); $this→assertJsonStringEqualsJsonString($expectedContent, $this→client→getResponse()→getContent()); } Przykład w PHP
  11. 11. Implementacja w pamięci
  12. 12. Zady i Walety + bardzo szybkie + często uruchamiane + wymusza dobre praktyki + łatwo się z nich wycofać - mniejsze pewność i wiarygodność - trudny i wolny development - dużo dodatkowego kodu - trudne do wprowadzenia w legacy
  13. 13. services_test.yaml PresentationDomainUserRepositoryInterface: '@PresentationTestsUtilsRepositoryUserInMemoryRepository' PresentationApplicationQueryListUsersQueryInterface: '@PresentationTestsUtilsQueryListUsersInMemoryQuery' PresentationApplicationQueryUniqueEmailQueryInterface: '@PresentationTestsUtilsQueryUniqueEmailInMemoryQuery' Przykład w PHP
  14. 14. interface UserRepositoryInterface { public function save(User $user): void; } final class UserRepository implements UserRepositoryInterface { public function __construct(private EntityManager $entityManager) {} public function save(User $user): void { $this→entityManager→persist($user); $this→entityManager→flush(); } } Przykład w PHP
  15. 15. final class UserInMemoryRepository implements UserRepositoryInterface { private array $users = []; public function save(User $user): void { $this→users[$user→getId()→toString()] = $user; } public function getOneByEmail(string $email): User { foreach ($this→users as $user) { if ($email === $user→getEmail()→toString()) { return $user; } } throw new UserNotFoundException(); } public function findAll(): array { return array_values($this→users); } } Przykład w PHP
  16. 16. interface ListUsersQueryInterface { /** @return User[] */ public function execute(): array; } final class ListUsersInMemoryQuery implements ListUsersQueryInterface { public function __construct(private UserInMemoryRepository $repository) {} public function execute(): array { return array_map( fn (User $user) ⇒ new DTO( $user→getId()→toString(), $user→getEmail()→toString(), $user→getName()→toString() ), $this→repository→findAll() ); } } Przykład w PHP
  17. 17. interface UniqueEmailQueryInterface { public function execute(string $email, ?string $contextId = null): bool; } final class UniqueEmailInMemoryQuery implements UniqueEmailQueryInterface { public function __construct(private UserInMemoryRepository $repository) {} public function execute(string $email, ?string $contextId = null): bool { try { $user = $this→repository→getOneByEmail($email); } catch (UserNotFoundException) { return true; } return (string) $contextId === $user→getId()→toString(); } } Przykład w PHP
  18. 18. final class UserAPITest extends WebTestCase { private KernelBrowser $client; private UserFixture $fixtures; public function testGivenValidPayloadWhenCreatingUserShouldReturn201(): void {...} public function testGivenNoParametersWhenListingUsersShouldReturn200WithAllUsers(): void {...} protected function setUp(): void {...} } Przykład w PHP
  19. 19. protected function setUp(): void { $this→client = static::createClient(); $this→fixtures = $this→client→getContainer()→get(UserFixture::class); } Przykład w PHP
  20. 20. public function testGivenValidPayloadWhenCreatingUserShouldReturn201(): void { $body = [ 'name' ⇒ 'John Doe', 'email' ⇒ 'john.doe@example.com' ]; $this→client→jsonRequest('POST', 'users', $body); $this→assertResponseStatusCodeSame(Response::HTTP_CREATED); } Przykład w PHP
  21. 21. public function testGivenNoParametersWhenListingUsersShouldReturn200WithAllUsers(): void { $this→fixtures→load(); $expectedContent = ' [ { "id": "4a4e03b2-5acc-4693-9d1f-dbc2d5662ee4", "email": "john.doe@example.com", "name": "John Doe" }, { "id": "3b3e03b2-5acc-4693-9d1f-dbc2d5662ff1", "email": "jane.dawson@example.com", "name": "Jane Dawson" } ] '; $this→client→request('GET', 'users'); $this→assertResponseStatusCodeSame(Response::HTTP_OK); $this→assertJsonStringEqualsJsonString($expectedContent, $this→client→getResponse()→getContent()); } Przykład w PHP
  22. 22. Porównanie rozwiązań
  23. 23. Porównanie rozwiązań W pamięci PHPUnit 9.5.20 ........................................ 40 / 40 (100%) Time: 00:00.637, Memory: 22.00 MB OK (40 tests, 100 assertions) Baza danych PHPUnit 9.5.20 ........................................ 40 / 40 (100%) Time: 03:05.990, Memory: 36.00 MB OK (40 tests, 100 assertions)
  24. 24. Rollback
  25. 25. Sqlite i inne tego typu
  26. 26. Podsumowanie
  27. 27. Bonus
  28. 28. public function testInvoke_whenIsCalled_shouldAddNewUser(): void { $command = new CreateUserCommand( '1f1450f0-e016-4ddd-a221-39c933bc5ac1', 'john.doe@example.com', 'John', 'Doe', 'password' ); $repository = $this→prophesize(UserRepositoryInterface::class); $SUT = new CreateUserHandler($repository→reveal()); $SUT($command); $repository→save(Argument::type(User::class))→shouldHaveBeenCalled(); } In Memory w testach jednostkowych
  29. 29. public function testInvoke_whenIsCalled_shouldAddNewUser(): void { $id = '1f1450f0-e016-4ddd-a221-39c933bc5ac1'; $command = new CreateUserCommand( $id, 'john.doe@example.com', 'John', 'Doe', 'password' ); $repository = new UserInMemoryRepository(); $SUT = new CreateUserHandler($repository); $SUT($command); self::assertInstanceOf(User::class, $repository→get(new UserId($id))); } In Memory w testach jednostkowych
  30. 30. Q&A

×