为什么 PHPSpec 正在进入 mocked/stubed 方法?
Why PHPSpec is stepping into mocked/stubed method?
我刚开始使用 PHPSpec,但遇到了一些问题。
其中之一是我不断收到
method call:
- find(null)
on Double\TaskRepositoryInterface\TaskRepositoryInterface\P95 was not expected, expected calls were:
- findOneByGoogleId(exact("googleId"))
I don't know why phpspec is expecting findOneByGoogleId there.
这是我的规格示例:
public function it_should_synchronize_new_task_from_google_to_app(
TaskDTO $taskDTO,
TaskDTO $taskDTO2,
TaskListDTO $taskListDTO,
TaskRepositoryInterface $taskRepository,
TaskListRepositoryInterface $taskListRepository,
TaskList $taskList,
AddTask $addTask
){
$taskDTO->getGoogleId()->willReturn('googleId');
$taskRepository->findOneByGoogleId('googleId')->willReturn(null);
$taskDTO->getTitle()->willReturn('GoogleTitle');
$taskListDTO->getId()->willReturn(1);
$taskListRepository->find(1)->willReturn($taskList);
//$addTask->toTaskList(Prophecy\Argument::type(TaskDTO::class),Prophecy\Argument::type(TaskListDTO::class))->shouldBeCalled();
//$addTask->toTaskList(Prophecy\Argument::type(TaskDTO::class),Prophecy\Argument::type(TaskListDTO::class))->shouldBeCalled()->willReturn($taskDTO2);
$addTask->toTaskList(Prophecy\Argument::type(TaskDTO::class),Prophecy\Argument::type(TaskListDTO::class))->willReturn($taskDTO2);
$this->fromGoogleToApp($taskDTO, $taskListDTO)->shouldReturnAnInstanceOf('Itmore\Core\Entity\TaskDTO');
}
这是 SUS:
public function fromGoogleToApp(TaskDTO $taskDTO, TaskListDTO $taskListDTO)
{
if(!$taskDTO->getGoogleId()){
throw new \ErrorException('not a google task');
}
$task = $this->taskRepository->findOneByGoogleId($taskDTO->getGoogleId());
if(!$task){
$task = new Task();
$task->setTitle($taskDTO->getTitle());
$taskList = $this->taskListRepository->find($taskListDTO->getId());
$task->setTaskList($taskList);
$addTask = new AddTask($this->taskRepository, $this->taskListRepository,$this->userRepository);
try {
$addTask->toTaskList(new TaskDTO($task), $taskListDTO);
} catch (\ErrorException $e) {}
return new TaskDTO($task);
}else {
if ($task->getTitle() != $taskDTO->getTitle()) {
$task->setTitle($taskDTO->getTitle());
}
$this->taskRepository->update();
}
return new TaskDTO($task);
}
这是 PHPSpec 介入的方法:
public function toTaskList(TaskDTO $taskDTO, TaskListDTO $taskListDTO)
{
$taskList = $this->taskListRepository->find($taskListDTO->getId());
if (!$taskList) {
throw new \ErrorException('taskList not found');
}
$task = $this->taskRepository->find($taskDTO->getId());
if ($task) {
throw new \ErrorException('task already exists');
}
$task = new Task();
$task->setTitle($taskDTO->getTitle());
$task->setGoogleId($taskDTO->getGoogleId());
$task->setTaskList($taskList);
$this->taskRepository->add($task);
return new TaskDTO($task);
}
如您所见,我尝试了不同的方法来 stub/mock 这个 toTaskList 方法,但它似乎不起作用。当我注释掉对 toTaskList 测试通过的调用时。我真的不明白为什么会这样。
您正在调用 $taskListDTO->getId() 两次,但只存根一次。
我会将您的 SUS 重构为如下所示:
public function fromGoogleToApp(TaskDTO $taskDTO, TaskListDTO $taskListDTO)
{
if(!$taskDTO->getGoogleId()){
throw new \ErrorException('not a google task');
}
$task = $this->taskRepository->findOneByGoogleId($taskDTO->getGoogleId());
if(!$task){
$taskList = $this->taskListRepository->find($taskListDTO->getId());
$task = $this->taskManager->createNew()
->setTitle($taskDTO->getTitle())
->setTaskList($taskList);
$addTask = $this->addTaskManager->createNew($this->taskRepository, $this->taskListRepository,$this->userRepository);
$newTaskDTO = $this->taskDTOManager->createNew($task);
try {
$addTask->toTaskList($newTaskDTO, $taskListDTO);
} catch (\ErrorException $e) {}
return $newTaskDTO;
}else {
if ($task->getTitle() != $taskDTO->getTitle()) {
$task->setTitle($taskDTO->getTitle());
}
$this->taskRepository->update();
}
return $this->taskDTOManager->createNew($task);;
}
这利用了 DI,您可以 stub/mock 调用。
当您指定它时,您可能会注意到您需要模拟和存根很多事情,这通常暗示该方法做了太多事情,将一些任务委托给其他人可能是个好主意类.
我刚开始使用 PHPSpec,但遇到了一些问题。 其中之一是我不断收到
method call: - find(null) on Double\TaskRepositoryInterface\TaskRepositoryInterface\P95 was not expected, expected calls were: - findOneByGoogleId(exact("googleId")) I don't know why phpspec is expecting findOneByGoogleId there.
这是我的规格示例:
public function it_should_synchronize_new_task_from_google_to_app(
TaskDTO $taskDTO,
TaskDTO $taskDTO2,
TaskListDTO $taskListDTO,
TaskRepositoryInterface $taskRepository,
TaskListRepositoryInterface $taskListRepository,
TaskList $taskList,
AddTask $addTask
){
$taskDTO->getGoogleId()->willReturn('googleId');
$taskRepository->findOneByGoogleId('googleId')->willReturn(null);
$taskDTO->getTitle()->willReturn('GoogleTitle');
$taskListDTO->getId()->willReturn(1);
$taskListRepository->find(1)->willReturn($taskList);
//$addTask->toTaskList(Prophecy\Argument::type(TaskDTO::class),Prophecy\Argument::type(TaskListDTO::class))->shouldBeCalled();
//$addTask->toTaskList(Prophecy\Argument::type(TaskDTO::class),Prophecy\Argument::type(TaskListDTO::class))->shouldBeCalled()->willReturn($taskDTO2);
$addTask->toTaskList(Prophecy\Argument::type(TaskDTO::class),Prophecy\Argument::type(TaskListDTO::class))->willReturn($taskDTO2);
$this->fromGoogleToApp($taskDTO, $taskListDTO)->shouldReturnAnInstanceOf('Itmore\Core\Entity\TaskDTO');
}
这是 SUS:
public function fromGoogleToApp(TaskDTO $taskDTO, TaskListDTO $taskListDTO)
{
if(!$taskDTO->getGoogleId()){
throw new \ErrorException('not a google task');
}
$task = $this->taskRepository->findOneByGoogleId($taskDTO->getGoogleId());
if(!$task){
$task = new Task();
$task->setTitle($taskDTO->getTitle());
$taskList = $this->taskListRepository->find($taskListDTO->getId());
$task->setTaskList($taskList);
$addTask = new AddTask($this->taskRepository, $this->taskListRepository,$this->userRepository);
try {
$addTask->toTaskList(new TaskDTO($task), $taskListDTO);
} catch (\ErrorException $e) {}
return new TaskDTO($task);
}else {
if ($task->getTitle() != $taskDTO->getTitle()) {
$task->setTitle($taskDTO->getTitle());
}
$this->taskRepository->update();
}
return new TaskDTO($task);
}
这是 PHPSpec 介入的方法:
public function toTaskList(TaskDTO $taskDTO, TaskListDTO $taskListDTO)
{
$taskList = $this->taskListRepository->find($taskListDTO->getId());
if (!$taskList) {
throw new \ErrorException('taskList not found');
}
$task = $this->taskRepository->find($taskDTO->getId());
if ($task) {
throw new \ErrorException('task already exists');
}
$task = new Task();
$task->setTitle($taskDTO->getTitle());
$task->setGoogleId($taskDTO->getGoogleId());
$task->setTaskList($taskList);
$this->taskRepository->add($task);
return new TaskDTO($task);
}
如您所见,我尝试了不同的方法来 stub/mock 这个 toTaskList 方法,但它似乎不起作用。当我注释掉对 toTaskList 测试通过的调用时。我真的不明白为什么会这样。
您正在调用 $taskListDTO->getId() 两次,但只存根一次。
我会将您的 SUS 重构为如下所示:
public function fromGoogleToApp(TaskDTO $taskDTO, TaskListDTO $taskListDTO)
{
if(!$taskDTO->getGoogleId()){
throw new \ErrorException('not a google task');
}
$task = $this->taskRepository->findOneByGoogleId($taskDTO->getGoogleId());
if(!$task){
$taskList = $this->taskListRepository->find($taskListDTO->getId());
$task = $this->taskManager->createNew()
->setTitle($taskDTO->getTitle())
->setTaskList($taskList);
$addTask = $this->addTaskManager->createNew($this->taskRepository, $this->taskListRepository,$this->userRepository);
$newTaskDTO = $this->taskDTOManager->createNew($task);
try {
$addTask->toTaskList($newTaskDTO, $taskListDTO);
} catch (\ErrorException $e) {}
return $newTaskDTO;
}else {
if ($task->getTitle() != $taskDTO->getTitle()) {
$task->setTitle($taskDTO->getTitle());
}
$this->taskRepository->update();
}
return $this->taskDTOManager->createNew($task);;
}
这利用了 DI,您可以 stub/mock 调用。
当您指定它时,您可能会注意到您需要模拟和存根很多事情,这通常暗示该方法做了太多事情,将一些任务委托给其他人可能是个好主意类.