PhpSpec 正确测试服务层
PhpSpec testing service layers correctly
该应用程序有多个服务,一些功能与多个服务重叠。由于 PhpSpec wraps objects 我一次只能测试一项服务。
背景:
群组服务 可以创建 "Red cars"、"Blue cars" 等群组。
汽车服务 可以将汽车分配给组。
群发服务:
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);
}
}
您的汽车服务规范应如下所示:
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);
}
}
该应用程序有多个服务,一些功能与多个服务重叠。由于 PhpSpec wraps objects 我一次只能测试一项服务。
背景:
群组服务 可以创建 "Red cars"、"Blue cars" 等群组。 汽车服务 可以将汽车分配给组。
群发服务:
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);
}
}
您的汽车服务规范应如下所示:
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);
}
}