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