PhpSpec тестирует сервисные слои правильно - PullRequest
0 голосов
/ 27 августа 2018

Приложение имеет несколько служб, и некоторые функции перекрывают несколько служб. Так как PhpSpec охватывает объекты , я могу протестировать только один сервис за один раз.

Справка:

Групповой сервис может создавать группы типа "Красные машины", "Синие автомобили". автосервис может назначать автомобили на группы.

Групповое обслуживание:

function createGroup($name);

Автосервис:

function assignCarToGroup($car, $group);

Проблема:

Когда я описываю автосервис в PhpSpec, я хочу убедиться, что он может проверить, был ли автомобиль успешно назначен группе.

Для этого группа должна существовать до назначения ей автомобиля.

Вопросы:

Мне нужно создать группу перед запуском файла. Вот где я сталкиваюсь с проблемой.

Если бы я создавал группы, опираясь на предыдущие примеры (GroupServiceSpec), я бы сделал тест очень хрупким.

Как я могу проверить, был ли автомобиль назначен успешно только в автосервисе?

GroupService.php

<?php

namespace App;

class GroupService
{
    private $group_repository;

    public function __construct($group_repository)
    {
        $this->group_repository = $group_repository;
    }

    public function CreateGroupServiceCall($name)
    {
        return $this->group_repository->createGroup($name);
    }
}

GroupRepository.php

<?php

namespace App;

class GroupRepository
{
    public function createGroup($name)
    {
        file_put_contents($name . '.db', '');

        return true;
    }
}

CarService.php

<?php

namespace App;

class CarService
{
    private $car_repository;

    public function __construct($car_repository)
    {
        $this->car_repository = $car_repository;
    }

    public function AssignCarToGroupServiceCall($car, $group_name)
    {
        return $this->car_repository->assignCarToGroup($car, $group_name);
    }
}

CarRepository.php

<?php

namespace app;

class CarRepository
{
    public function assignCarToGroup($car, $name)
    {
        $file_path = $name . '.db';

        if (file_exists($file_path) == true) {
            file_put_contents($file_path, $car);

            return true;
        } else {
            return false;
        }
    }
}

А вот и тесты:

GroupServiceSpec.php

<?php

namespace spec\App;

use App\GroupRepository;
use App\GroupService;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class GroupServiceSpec extends ObjectBehavior
{

    function let()
    {
        $group_repository = new GroupRepository();
        $this->beConstructedWith($group_repository);
    }

    function letGo()
    {
        # Clean up and remove all DB files
        array_map('unlink', glob(__DIR__ . "/../../*.db"));
    }

    function it_is_initializable()
    {
        $this->shouldHaveType(GroupService::class);
    }

    function it_can_create_a_group()
    {
        $this->CreateGroupServiceCall('New Group')->shouldBe(true);
    }

}

GroupRepositorySpec.php

<?php

namespace spec\App;

use App\GroupRepository;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class GroupRepositorySpec extends ObjectBehavior
{

    function letGo()
    {
        # Clean up and remove all DB files
        array_map('unlink', glob(__DIR__ . "/../../*.db"));
    }

    function it_is_initializable()
    {
        $this->shouldHaveType(GroupRepository::class);
    }

    function it_can_create_group()
    {
        $status = $this->createGroup('test');
        $status->shouldBe(true);
    }
}

CarServiceSpec.php

<?php

namespace spec\App;

use App\CarRepository;
use App\CarService;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class CarServiceSpec extends ObjectBehavior
{

    function let()
    {
        $car_repository = new CarRepository();
        $this->beConstructedWith($car_repository);
    }

    function it_is_initializable()
    {
        $this->shouldHaveType(CarService::class);
    }

    function it_can_assign_car_to_group()
    {
        $car = 'Car I';
        $group_name = 'Group1';

        $this->AssignCarToGroupServiceCall($car, $group_name)->shouldBe(true);
    }
}

CarRepositorySpec.php

<?php

namespace spec\App;

use app\CarRepository;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class CarRepositorySpec extends ObjectBehavior
{
    function it_is_initializable()
    {
        $this->shouldHaveType(CarRepository::class);
    }

    function it_can_assign_car_to_group()
    {
        # how can I test this part, as the group is not existing now.
        # If I'm not to create the group, how can I test if this code works at all?
        # Do I have a design error?

        $car = 'Car1';
        $group_name = 'Company';

        $this->assignCarToGroup($car, $group_name)->shouldBe(true);
    }
}

1 Ответ

0 голосов
/ 28 августа 2018

Спецификация вашего автосервиса должна выглядеть следующим образом:

class CarServiceSpec extends ObjectBehavior
{

  function let(CarRepository $carRepository)
  {
    $this->beConstructedWith($carRepository);
  }

  function it_is_initializable()
  {
    $this->shouldHaveType(CarService::class);
  }

  function it_can_assign_car_to_group(CarRepository $carRepository)
  {
    $car = 'Car I';
    $group_name = 'Group1';

    $carRepository->assignCarToGroup($car, $group_name)->shouldBeCalled()->willReturn(true);

    $this->AssignCarToGroupServiceCall($car, $group_name)->shouldReturn(true);
  }
}
...