Проблема в тестировании с withConsecutive () - PullRequest
2 голосов
/ 07 февраля 2020

У меня есть класс FillUserPaymentStatisticService с методами:

public function fillStatisticForAllTime(): void
    {
        $firstDate = \DateTime::createFromFormat('Y-m-d H:i:s', $this->userPaymentsRepository->getTheOldestDate());
        $lastDate = (new \DateTime())->setTime(0, 0, 0);
        while ($firstDate < $lastDate) {
            $this->fillStatistic($firstDate);
            $firstDate->add(new \DateInterval('P1D'));
        }



private function fillStatistic(\DateTime $day): void
    {
        $dateFrom = $day->setTime(0, 0, 0);
        $dateTo = clone $day;
        $dateTo->setTime(23, 59, 59);

        $statisticAll = $this->userPaymentsRepository
            ->getSummaryStatistic(['dateFrom' => $dateFrom, 'dateTo' => $dateTo, 'onlyPaid' => false]);
        $this->userPaymentsStatisticRepository->insertDailyStatistic($statisticAll, $day, false);

        $statisticOnlyPaid = $this->userPaymentsRepository
            ->getSummaryStatistic(['dateFrom' => $dateFrom, 'dateTo' => $dateTo, 'onlyPaid' => true]);
        $this->userPaymentsStatisticRepository->insertDailyStatistic($statisticOnlyPaid, $day, true);
    }
}

И я пытаюсь написать тест:

public function testFillStatisticForAllTime(): void
{
    $dateFromFirst = (new \DateTime())->sub(new \DateInterval('P2D'))->setTime(0, 0, 0);
    $dateToFirst = (new \DateTime())->sub(new \DateInterval('P2D'))->setTime(23, 59, 59);

    $dateFromSecond = (new \DateTime())->sub(new \DateInterval('P1D'))->setTime(0, 0, 0);
    $dateToSecond = (new \DateTime())->sub(new \DateInterval('P1D'))->setTime(23, 59, 59);

    $statistic = ['addPeopleFromPlugin' => 10];
    $statisticOnlyPaid = ['addPeopleFromPlugin' => 7];

    $this->userPaymentsRepositoryMock->expects($this->once())
        ->method('getTheOldestDate')
        ->willReturn($dateFromFirst->format('Y-m-d H:i:s'));

    $this->userPaymentsRepositoryMock->expects($this->exactly(4))
        ->method('getSummaryStatistic')
        ->withConsecutive(
            [['dateFrom' => $dateFromFirst, 'dateTo' => $dateToFirst, 'onlyPaid' => false]],
            [['dateFrom' => $dateFromFirst, 'dateTo' => $dateToFirst, 'onlyPaid' => true]],
            [['dateFrom' => $dateFromSecond, 'dateTo' => $dateToSecond, 'onlyPaid' => false]],
            [['dateFrom' => $dateFromSecond, 'dateTo' => $dateToSecond, 'onlyPaid' => true]],
        )
        ->willReturnOnConsecutiveCalls($statistic, $statisticOnlyPaid, $statistic, $statisticOnlyPaid);

    $this->userPaymentsStatisticRepositoryMock->expects($this->exactly(4))
        ->method('insertDailyStatistic')
        ->withConsecutive(
            [$statistic, $dateFromFirst, false],
            [$statisticOnlyPaid, $dateFromFirst, true],
            [$statistic, $dateFromSecond, false],
            [$statisticOnlyPaid, $dateFromSecond, true],
        );

    $this->fillUserPaymentStatisticService->fillStatisticForAllTime();
}

И у меня возникла ошибка:

Параметр 0 для invocation # 0 App \ Repositories \ Members \ Billing \ UserPaymentsRepository :: getSummaryStatisti c (Array (...)): массив не соответствует ожидаемому значению.

Ожидается: Array ('dateFrom' => 2020-02-05T00: 00: 00.000000 + 0000 'dateTo' => Объект DateTime (...) 'onlyPaid' => false) Факт: Массив ('dateFrom' => 2020-02-06T00: 00: 00.000000 +0000 'dateTo' => DateTime Object (...) 'onlyPaid' => false)

Если сегодня 2020-02-07, то первая дата должна быть 2020-02-06, а вторая 2020 -02-05, почему в тесте дата 2020-02-06?

Когда я меняю метод fillStatisticForAllTime, например:

 while ($firstDate < $lastDate) {
            $date = \DateTime::createFromFormat('U', $firstDate->format('U'));
            $this->fillStatistic($date);
            $firstDate->add(new \DateInterval('P1D'));
        }

его работа становится правильной

1 Ответ

3 голосов
/ 13 февраля 2020

Основная проблема заключается в том, что ваши переменные являются изменяемыми объектами (переданными по ссылке) .

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

FIX: Клонировать любую дату («отделить» от исходной переменной) перед ее использованием.

public function fillStatisticForAllTime(): void
{
    $firstDate = \DateTime::createFromFormat('Y-m-d H:i:s', $this->userPaymentsRepository->getTheOldestDate());
    $lastDate  = (new \DateTime())->setTime(0, 0, 0);
    while ($firstDate < $lastDate) {
        $this->fillStatistic(clone $firstDate); // <--------------- clone date
        $firstDate->add(new \DateInterval('P1D'));
    }
}


private function fillStatistic(\DateTime $day): void
{
    $dateFrom = clone $day; // <----------------------------------- clone date
    $dateFrom->setTime(0, 0, 0);
    $dateTo = clone $day;
    $dateTo->setTime(23, 59, 59);

    $statisticAll = $this->userPaymentsRepository
        ->getSummaryStatistic(['dateFrom' => $dateFrom, 'dateTo' => $dateTo, 'onlyPaid' => false]);
    $this->userPaymentsStatisticRepository->insertDailyStatistic($statisticAll, $day, false);

    $statisticOnlyPaid = $this->userPaymentsRepository
        ->getSummaryStatistic(['dateFrom' => $dateFrom, 'dateTo' => $dateTo, 'onlyPaid' => true]);
    $this->userPaymentsStatisticRepository->insertDailyStatistic($statisticOnlyPaid, $day, true);
}

Кстати, ваш второй подход работает, потому что вы создаете новый объект («detact» из исходной переменной)

Чтобы избежать подобных ошибок в будущем, вы можете использовать неизменяемые объекты даты .

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