[PHPUnit]、[Symfony]:エンティティがDBに保存されたことをテストします

PawelC

テストに問題があります。phpunitテストの書き方と、オブジェクトやサービスなどをモックする方法を学びます。ProductServiceに次のメソッドがあります。

<?php

namespace App\Service;

use App\Entity\Product;
use App\Repository\ProductRepository;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\ORMException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class ProductService
{
    /**
     * @var ProductRepository
     */
    private $productRepository;
    /**
     * @var EntityManager
     */
    private $entityManager;
    /**
     * @var ValidatorInterface
     */
    private $validator;

    /**
     * ProductService constructor.
     * @param ProductRepository $productRepository
     * @param EntityManagerInterface $entityManager
     * @param ValidatorInterface $validator
     */
    public function __construct(ProductRepository $productRepository, EntityManagerInterface $entityManager, ValidatorInterface $validator)
    {
        $this->productRepository = $productRepository;
        $this->entityManager = $entityManager;
        $this->validator = $validator;
    }

    /**
     * @param $productData
     * @return Product|string
     */
    public function createProduct($productData)
    {
        $name = $productData['name'];
        $quantity = $productData['quantity'];
        $sku = $productData['sku'];

        $product = new Product();
        $product->setName($name);
        $product->setQuantity($quantity);
        $product->setProductSerial($sku);

        $errors = $this->validator->validate($product);

        if (count($errors) > 0) {
            $errorsString = (string)$errors;

            return $errorsString;
        }

        try {
            $this->entityManager->persist($product);
            $this->entityManager->flush();
            return $product;
        } catch (\Exception $ex) {
            return $ex->getMessage();
        }
    }
}

そして私はこのテストを書きます:

<?php

namespace App\Tests\Service;

use App\Entity\Product;
use App\Repository\ProductRepository;
use App\Service\ProductService;
use Doctrine\Common\Persistence\ObjectRepository;
use PHPUnit\Framework\TestCase;

class ProductServiceTest extends TestCase
{
    /**
     * Create product test
     */
    public function testCreateProduct()
    {
        $product = new Product();
        $product->setName('tester');
        $product->setQuantity(2);
        $product->setProductSerial('Examplecode');

        $productService = $this->createMock(ProductService::class);
        $productService->method('createProduct')->will($this->returnSelf());
        $this->assertSame($productService, $productService->createProduct($product));
    }
}

phpunitテストを実行すると、常に成功しますが、データベースは空です。テストが正しく機能することをどのように確認できますか?修正する価値があるものとそうでないものは何ですか?たとえば、テストデータベースにレコードを追加するなど、テストの起動結果を作成したかったのですが、その方法と適切なモックの方法がわかりません。私はphpunit + Symfony4を使用しています。

以前はテストを作成していましたが、エンドポイントAPIを要求するテストでした。ここでは、エンドポイントなしでサービスとリポジトリをテストしたいと思います。

ウェブサイト、リポジトリ、さまざまなクラスなどをテストしてモックする方法を学びたいです。

私が答えを適用するとき、私は持っています:

PHPUnit 7.5.17 by Sebastian Bergmann and contributors.

Testing Project Test Suite
?[31;1mE?[0m                                                                   1 / 1 (100%)

Time: 542 ms, Memory: 10.00 MB

There was 1 error:

1) App\Tests\Service\ProductServiceTest::testCreateProduct
Doctrine\Common\Persistence\Mapping\MappingException: The class 'App\Repository\ProductRepository' was not found in the chain configured namespaces App\Entity, Gesdinet\JWTRefreshTokenBundle\Entity

D:\warehouse-management-api\vendor\doctrine\persistence\lib\Doctrine\Common\Persistence\Mapping\MappingException.php:22
D:\warehouse-management-api\vendor\doctrine\persistence\lib\Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain.php:87
D:\warehouse-management-api\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\ClassMetadataFactory.php:151
D:\warehouse-management-api\vendor\doctrine\persistence\lib\Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory.php:304
D:\warehouse-management-api\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\ClassMetadataFactory.php:78
D:\warehouse-management-api\vendor\doctrine\persistence\lib\Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory.php:183
D:\warehouse-management-api\vendor\doctrine\orm\lib\Doctrine\ORM\EntityManager.php:283
D:\warehouse-management-api\vendor\doctrine\doctrine-bundle\Repository\ContainerRepositoryFactory.php:44
D:\warehouse-management-api\vendor\doctrine\orm\lib\Doctrine\ORM\EntityManager.php:713
D:\warehouse-management-api\vendor\doctrine\persistence\lib\Doctrine\Common\Persistence\AbstractManagerRegistry.php:215
D:\warehouse-management-api\tests\Service\ProductServiceTest.php:28

?[37;41mERRORS!?[0m
?[37;41mTests: 1?[0m?[37;41m, Assertions: 0?[0m?[37;41m, Errors: 1?[0m?[37;41m.?[0m

私の製品エンティティ

<?php

namespace App\Entity;

use DateTime;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity(repositoryClass="App\Repository\ProductRepository")
 */
class Product
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank()
     */
    private $name;

    /**
     * @ORM\Column(type="integer")
     * @Assert\NotBlank()
     */
    private $quantity;

    /**
     * @Gedmo\Mapping\Annotation\Timestampable(on="create")
     * @ORM\Column(type="datetime")
     */
    private $createdAt;

    /**
     * @Gedmo\Mapping\Annotation\Timestampable(on="update")
     * @ORM\Column(type="datetime")
     */
    private $updatedAt;

    /**
     * @ORM\Column(type="string")
     * @Assert\NotBlank()
     */
    private $product_serial;


    public function __construct() {
        $this->setCreatedAt(new \DateTime());
        $this->setUpdatedAt();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getQuantity(): ?int
    {
        return $this->quantity;
    }

    public function setQuantity(int $quantity): self
    {
        $this->quantity = $quantity;

        return $this;
    }

    public function getCreatedAt(): ?\DateTimeInterface
    {
        return $this->createdAt;
    }

    public function setCreatedAt(\DateTimeInterface $createdAt): self
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    public function getUpdatedAt(): ?\DateTimeInterface
    {
        return $this->updatedAt;
    }

    public function setUpdatedAt(): self
    {
        $this->updatedAt = new \DateTime();

        return $this;
    }

    public function getProductSerial(): ?string
    {
        return $this->product_serial;
    }

    public function setProductSerial(string $product_serial): self
    {
        $this->product_serial = $product_serial;

        return $this;
    }
}

ProductRepository

<?php

namespace App\Repository;

use App\Entity\Product;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;

class ProductRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Product::class);
    }
}

doctrine.yaml

doctrine:
    dbal:
        # configure these for your database server
        driver: 'pdo_mysql'
        server_version: '5.7'
        charset: utf8mb4
        default_table_options:
            charset: utf8mb4
            collate: utf8mb4_unicode_ci

        url: '%env(resolve:DATABASE_URL)%'
    orm:
        auto_generate_proxy_classes: true
        naming_strategy: doctrine.orm.naming_strategy.underscore
        auto_mapping: true
        mappings:
            App:
                is_bundle: false
                type: annotation
                dir: '%kernel.project_dir%/src/Entity'
                prefix: 'App\Entity'
                alias: App
staskrak

まず、このテストでは、メソッドをモックすると、元のメソッドは存在しなくなります。あなたの場合、あなたはProductService::createProductこのようなものに置き換えます

// This is your mock
class ProductService 
{
    // ...

    public function createProduct($productData)
    {
        return $this;
    }
}

あなたのテストは何もチェックしません。

実際の機能をテストしたい場合は

namespace App\Tests\Service;

use App\Repository\ProductRepository;
use App\Service\ProductService;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class ProductServiceTest extends KernelTestCase
{
    /**
     * Create product test
     */
    public function testCreateProduct(): void
    {
        // We load the kernel here (and $container)
        self::bootKernel();

        $productData = [
            'name' => 'foo',
            'quantity' => 1,
            'sku' => 'bar',
        ];
        $productRepository = static::$container->get('doctrine')->getRepository(ProductRepository::class);
        $entityManager = static::$container->get('doctrine')->getManager();

        // Here we mock the validator.
        $validator = $this->getMockBuilder(ValidatorInterface::class)
            ->disableOriginalConstructor()
            ->setMethods(['validate'])
            ->getMock();

        $validator->expects($this->once())
            ->method('validate')
            ->willReturn(null);

        $productService = new ProductService($productRepository, $entityManager, $validator);

        $productFromMethod = $productService->createProduct($productData);

        // Here is you assertions:
        $this->assertSame($productData['name'], $productFromMethod->getName());
        $this->assertSame($productData['quantity'], $productFromMethod->getQuantity());
        $this->assertSame($productData['sku'], $productFromMethod->getSku());

        $productFromDB = $productRepository->findOneBy(['name' => $productData['name']]);

        // Here we test that product in DB and returned product are same
        $this->assertSame($productFromDB, $productFromMethod);
    }
}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

既存のエンティティを複製せずに、既存のネストされたエンティティとともに新しい切断されたエンティティを保存する

分類Dev

新しいエンティティをデータベースに保存しようとしましたが、生成されたIDがnullです

分類Dev

保存されたエンティティに追加された要素も作成されることを期待する必要がありますか?

分類Dev

エンティティがマップされたエンティティのリストにあるかどうかを確認します

分類Dev

symfonyがステートメント(where句)でマップされたエンティティを取得する

分類Dev

子エンティティが一意のフィールドの1つによって初期化されたときにエンティティを保存すると、org.springframework.dao.InvalidDataAccessApiUsageExceptionがスローされます。

分類Dev

JSONをWebAPI 2に投稿するときにエラーが発生しました:リクエストエンティティのメディアタイプ「text / plain」はこのリソースではサポートされていません

分類Dev

htmlページがテキストエディタでコーディングされて.htmlとして保存されるのと同じように、jpgファイルをコーディングしても同じことができますか?

分類Dev

複数のエンティティが共通のエンティティから派生し、同じテーブルに保存されている場合に、エンティティごとにオブジェクトをクエリする方法

分類Dev

Symfony は、削除フラグが設定されていないネストされたエンティティを取得します

分類Dev

MySQLに保存されているHTMLエンティティをTwig(Symfony)でデコードします

分類Dev

symfonyを使用してエンティティを作成しようとすると、中止されたエラーメッセージが表示されます

分類Dev

保存されたエンティティをキーでロードすることによるデータストアの強力な一貫性

分類Dev

キャッシュされたオブジェクトを含むエンティティを保存すると、切り離されたエンティティの例外が発生します

分類Dev

Firefoxのwebextensionアドオン設定ページで設定を保存しようとすると、「コンテキストが非アクティブのときにPromiseが解決されました」というエラーが発生します

分類Dev

DBから分離されたエンティティを削除します

分類Dev

SpringブートでJPAで保存するときに「更新された」保存されたエンティティを取得する方法はありますか?

分類Dev

分離されたエンティティまたは新しいエンティティをhibernate / jpaベストプラクティスの質問の既存のエンティティとマージする

分類Dev

Micronaut data jdbc:既存のエンティティを保存すると、既存のエンティティを更新する代わりに新しいエンティティが作成されます

分類Dev

symfony4でネストされたDateTimeオブジェクトを持つエンティティにjsonを逆シリアル化します

分類Dev

ボタンがクリックされたときにテキストフィールドとテキストエリアを追加します

分類Dev

Sequelize-関連付けを設定し、エンティティを保存し、保存されたエンティティを関連付けられたエンティティとともに返す方法

分類Dev

Hibernateエンティティをデタッチして、オブジェクトへの変更がデータベースに自動的に保存されないようにすることはできますか?

分類Dev

symfonyでエンティティが削除されたときにファイルを削除する

分類Dev

エンティティがコンテキストに存在しないため、タイプ 'MyTable' のエンティティに対してメンバー 'CurrentValues' を呼び出すことができません

分類Dev

DBに保存された保存済みエンティティのlastModifiedBy列を取得できません

分類Dev

エンティティにネストされたリンクは奇妙な結果を合計します

分類Dev

DataTableを動的に作成されたエンティティモデルにキャストしますか?

分類Dev

Entity FrameworkCore保存された依存関係を持つエンティティを追加するとエラーがスローされます

Related 関連記事

  1. 1

    既存のエンティティを複製せずに、既存のネストされたエンティティとともに新しい切断されたエンティティを保存する

  2. 2

    新しいエンティティをデータベースに保存しようとしましたが、生成されたIDがnullです

  3. 3

    保存されたエンティティに追加された要素も作成されることを期待する必要がありますか?

  4. 4

    エンティティがマップされたエンティティのリストにあるかどうかを確認します

  5. 5

    symfonyがステートメント(where句)でマップされたエンティティを取得する

  6. 6

    子エンティティが一意のフィールドの1つによって初期化されたときにエンティティを保存すると、org.springframework.dao.InvalidDataAccessApiUsageExceptionがスローされます。

  7. 7

    JSONをWebAPI 2に投稿するときにエラーが発生しました:リクエストエンティティのメディアタイプ「text / plain」はこのリソースではサポートされていません

  8. 8

    htmlページがテキストエディタでコーディングされて.htmlとして保存されるのと同じように、jpgファイルをコーディングしても同じことができますか?

  9. 9

    複数のエンティティが共通のエンティティから派生し、同じテーブルに保存されている場合に、エンティティごとにオブジェクトをクエリする方法

  10. 10

    Symfony は、削除フラグが設定されていないネストされたエンティティを取得します

  11. 11

    MySQLに保存されているHTMLエンティティをTwig(Symfony)でデコードします

  12. 12

    symfonyを使用してエンティティを作成しようとすると、中止されたエラーメッセージが表示されます

  13. 13

    保存されたエンティティをキーでロードすることによるデータストアの強力な一貫性

  14. 14

    キャッシュされたオブジェクトを含むエンティティを保存すると、切り離されたエンティティの例外が発生します

  15. 15

    Firefoxのwebextensionアドオン設定ページで設定を保存しようとすると、「コンテキストが非アクティブのときにPromiseが解決されました」というエラーが発生します

  16. 16

    DBから分離されたエンティティを削除します

  17. 17

    SpringブートでJPAで保存するときに「更新された」保存されたエンティティを取得する方法はありますか?

  18. 18

    分離されたエンティティまたは新しいエンティティをhibernate / jpaベストプラクティスの質問の既存のエンティティとマージする

  19. 19

    Micronaut data jdbc:既存のエンティティを保存すると、既存のエンティティを更新する代わりに新しいエンティティが作成されます

  20. 20

    symfony4でネストされたDateTimeオブジェクトを持つエンティティにjsonを逆シリアル化します

  21. 21

    ボタンがクリックされたときにテキストフィールドとテキストエリアを追加します

  22. 22

    Sequelize-関連付けを設定し、エンティティを保存し、保存されたエンティティを関連付けられたエンティティとともに返す方法

  23. 23

    Hibernateエンティティをデタッチして、オブジェクトへの変更がデータベースに自動的に保存されないようにすることはできますか?

  24. 24

    symfonyでエンティティが削除されたときにファイルを削除する

  25. 25

    エンティティがコンテキストに存在しないため、タイプ 'MyTable' のエンティティに対してメンバー 'CurrentValues' を呼び出すことができません

  26. 26

    DBに保存された保存済みエンティティのlastModifiedBy列を取得できません

  27. 27

    エンティティにネストされたリンクは奇妙な結果を合計します

  28. 28

    DataTableを動的に作成されたエンティティモデルにキャストしますか?

  29. 29

    Entity FrameworkCore保存された依存関係を持つエンティティを追加するとエラーがスローされます

ホットタグ

アーカイブ