Использование 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!');
}
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]