PHPUnit: лучшая практика, когда использовать сопоставитель вызова метода Mock Object

Я читал документы PHPUnit в Интернете и использовал средства сопоставления фиктивных объектов, но я не уверен, когда вы должны или не должны их использовать. Для приведенного ниже примера предположим, что у меня есть класс Foo, для которого я пишу тест:

Фу класс

<?php

class Foo {
     public function isUserNamedTom(User $user):bool
     {
          return strtoupper($user->getName()) === 'TOM'; 
     }
}

Мой тест

<?php

use PHPUnit\Framework\TestCase;

class FooTest extends TestCase {
     public function testIsUserNamedTom():void
     {
          $userMock = $this->getMockBuilder(User:class)
          ->disableOriginalConstructor()
          ->getMock();

          $userMock->expects($this->once())
          ->method('getName')
          ->willReturn('tom');

          $fooService = new Foo();
          $response = $fooService->isUserNamedTom($userMock);

          $this->assertTrue($response);
     }
}

Мой вопрос в том, должен ли я использовать $это->один раз() или нет в этом примере, и если нет, то по каким причинам.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
33
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

В этом случае кажется неуместным для проверки isUserNamedTom(User $user), вызывается ли user->getName() один раз, дважды или никогда. Важно только то, что isUserNamedTom(User $user) возвращает true тогда и только тогда, когда $user имеет имя «tom», «Tom», «tOm» и т. д.

Поэтому: Нет, я бы не стал проверять здесь $this->once().

Я бы даже попытался обойтись без насмешек и вместо этого передать созданный объект пользователя. Но возможно ли это, зависит от вашего User класса.

 public function testIsUserNamedTom():void
 {
      $user = (new User())->setName('tom');
      $this->assertTrue($fooService->isUserNamedTom($user));
 }

По сути, при написании тестов всегда полезно спросить себя, при каких обстоятельствах вы хотите, чтобы они провалились. В вашем примере я предполагаю, что ваш тест не должен терпеть неудачу, если кто-то рефакторинг isUserNamedTom(User $user) так, что метод больше не вызывает $user->getName() (но, возможно, использует общедоступное свойство $user->name).

Теперь это имеет смысл. Я убежден, что подсчет вызовов методов в этом примере не является хорошей идеей. Я не уверен, когда вы захотите его использовать (например, $this->once(), $this->at(0), $this->atLeastOnce()).

Kyle 06.04.2022 16:40

@Kyle Я часто использую его, когда хочу убедиться, что какая-то дорогостоящая операция (запрос к базе данных, вызов API, ...) не выполняется чаще, чем ожидалось.

simon.ro 06.04.2022 17:15

Другие вопросы по теме