Как я могу смоделировать результат метода в моем модульном тесте?

Я изучаю ООП и методы чистого кодирования, и для этого я начал создавать игру на основе веб-браузера в Laravel.

У меня есть класс ниже, который предоставляет мне случайное число, чтобы узнать, успешно ли действие или нет:

class GenericDice
{
    /**
     * 
     * @param int $min
     * @param int $max
     * @return int
     */
    public function random(int $min = 1, int $max = 100) : int
    {
        return mt_rand($min, $max);
    }
}

Теперь в своих тестах я хочу проверить, что когда GenericDice::random() возвращает 100, это означает, что я должен считать действие критическим сбоем.

Я прочитал документы Laravel Mocking, документы Mockery (в которых мне сказали не издеваться над статическими методами, поэтому я изменил способ использования класса GenericDice) и пробовал много разных способов сделать это, но я не могу заставить свои кости дать мне фиксированный результат.

Вот тест:

    public function test_character_should_lose_health_when_action_is_critical_failure()
    {
        $this->mock(GenericDice::class, function (MockInterface $mock) {
            $mock->shouldReceive("random")
                ->andReturn(100);
        });

        $character = Character::factory()->create([
            "current_health" => 50,
        ]);

        $response = $this->actingAs($character->user)->put(route("game.action.run"), [
            "ordre_id" => $this->cookAction->id,
        ]);

        $character->refresh();

        $this->assertLessThan(50, $character->current_health);
    }

Код, запускающий действие, выглядит следующим образом:

class CookAction extends AbstractAction 
{
    public function run(): bool
    {
        // Let's roll baby...
        $this->diceResult = $this->throwDice();

        // How did I do?
        $this->checkForSuccess();

        // The cooking part below.
    }
}

// Below the AbstractAction
abstract class AbstractAction
{
    protected function throwDice(int $min = 1, int $max = 100): int
    {
        return (new GenericDice)->random($min, $max);
    }
}

Что я делаю не так?

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

bassxzero 24.12.2020 02:10
Стоит ли изучать 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 и хотите разрабатывать...
1
1
222
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Похоже, вы правильно создаете макет, но не привязываете макет к контейнеру службы. Вы вручную создаете новый GenericDice вместо того, чтобы позволить сервис-контейнеру разрешить его. Создайте макет и привяжите его к контейнеру службы, а затем позвольте приложению разрешить экземпляр экземпляра GenericeDice для вас.

Попробуй это

public function test_character_should_lose_health_when_action_is_critical_failure()
{
    $diceMock = \Mockery::mock(GenericDice::class)->makePartial();
    $diceMock->shouldReceive('random')->andReturn(100);

    // Bind to service container
     $this->app->bind(
        GenericDice::class,
        function () use ($diceMock) {
            return $diceMock;
        }
    );

    $character = Character::factory()->create([
        "current_health" => 50,
    ]);

    $response = $this->actingAs($character->user)->put(route("game.action.run"), [
        "ordre_id" => $this->cookAction->id,
    ]);

    $character->refresh();

    $this->assertLessThan(50, $character->current_health);
}

И это

abstract class AbstractAction
{
    protected function throwDice(int $min = 1, int $max = 100): int
    {
          // Get the GenericeDice instance from the service container
          $dice = app(GenericDice::class);
          return $dice->random($min, $max);
    }
}

Спасибо! Теперь это работает! Мне определенно нужно больше узнать о контейнере Laravel, поскольку в моих знаниях этого явно не хватает.

rachids 24.12.2020 02:19

@RachidS Да, это полезная и хорошая практика даже за пределами Laravel.

bassxzero 24.12.2020 02:23

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