Использование ExpectException и шпион в PHPUnit

Я использую PHPUnit ~5.2 и PHP ~7.0.0,

У меня есть класс, который оборачивает репозиторий, ловит исключения, которые он выдает, вызывает регистратор и затем сбрасывает исключение.

public function storeDonation( Donation $donation ) {
    try {
        $this->repository->storeDonation( $donation );
    }
    catch ( StoreDonationException $ex ) {
        $this->logger->log( $this->logLevel, $ex->getMessage(), [ 'exception' => $ex ] );
        throw $ex;
    }
}

В своих тестах я создал шпиона для регистратора, чтобы я мог видеть, какие вызовы были сделаны для функций журналирования. Этот шпион является специальным двойным тестом, НЕ созданным с помощью API-интерфейса насмешки PHPUnit. Проблема, с которой я сталкиваюсь, не возникнет при использовании API-интерфейса для пересмотра PHPUnit, однако я не спрашиваю об этом решении.

Тестовый метод, в котором я сталкиваюсь с проблемами, имеет некоторый установочный код, затем он вызывает PHPUnits. expectException (который раньше был setExpectedException в PHPUnit 5.1 и более ранних версиях), затем вызывает производственный метод и, наконец, получает вызовы от шпиона, чтобы подтвердить правильность тех, где они были сделаны.

public function testWhenGetDonationByIdThrowException_itIsLoggedAndThrown() {
    $logger = new LoggerSpy();

    $loggingRepo = new LoggingDonationRepository(
        $this->newThrowingRepository(),
        $logger
    );

    $this->expectException( GetDonationException::class );
    $loggingRepo->getDonationById( 1337 );

    $this->assertEquals(
        [
            [
                LogLevel::CRITICAL,
                self::GET_DONATION_BY_ID_EXCEPTION_MESSAGE,
                $this->newGetDonationException()
            ]
        ],
        $logger->getLogCalls()
    );
}

Проблема в том, что когда генерируется исключение, PHPUnit ловит его и оценивает expectException, после которого выполнение моего метода испытаний не продолжается. Таким образом, утверждения с использованием моего шпиона никогда не выполняются.

Я ищу способ решить эту проблему. Я решил разделить метод на тот, который имеет expectException часть, а другая, которая имеет как фиктивную попытку для вызова производственного кода, так и утверждения для шпиона. Какие-нибудь предложения более хороших подходов?

1 ответ

Решение

Когда вы генерируете исключение, весь следующий код прерывается до оператора catch. Это также относится и к вашему методу испытаний.

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

Так что да, вам нужно будет написать свой собственный try catch блокировать, если вы хотите выполнять другие проверки после исключения. Вот пример того, как вы это сделаете:

public function testWhenGetDonationByIdThrowException_itIsLoggedAndThrown() {
    $logger = new LoggerSpy();

    $loggingRepo = new LoggingDonationRepository(
        $this->newThrowingRepository(),
        $logger
    );

    try {
        $loggingRepo->getDonationById( 1337 );
    } catch (GetDonationException $e) {
        $this->assertEquals(
            [[
                LogLevel::CRITICAL,
                self::GET_DONATION_BY_ID_EXCEPTION_MESSAGE,
                $this->newGetDonationException()
            ]],
            $loger->getLogCalls()
        );

        return;
    }

    $this->fail('Expected exception wasn\'t thrown!');
}
Другие вопросы по тегам