У меня есть такой пример, который основан на генераторе ключей Laravel:
public function generateRandomKey(): string
{
$generatedKey = base64_encode(random_bytes(16));
// Encrypt the generated key with our public key so it is not a 'plain password' anymore.
$value = openssl_public_encrypt($generatedKey, $crypted, $this->getPublicKey());
if (!$value) {
throw new \RuntimeException('Encryption failed: could not generate a random key.');
}
return base64_encode($crypted);
}
Я хотел бы провести модульные тесты, и я могу ожидать RuntimeException
, Я хотел бы иметь 100% покрытие кода, но я также не хочу форсировать сценарий только для того, чтобы получить 100% покрытие кода.
В этом примере я бы хотел, чтобы PHPUnit ударил исключение. Я не могу предоставить неправильный ключ, потому что мой getPublicKey()
является частным и выдаст ошибку, прежде чем я доберусь до ошибки в этом методе.
Вызвать ошибки дешифрования не так сложно, так как я могу просто указать случайное значение, которое не было должным образом зашифровано.
Итак, как я смогу протестировать подобный сценарий и достичь 100% покрытия кода. Возможно ли или даже целесообразно протестировать что-то подобное или лучше игнорировать это комментарием PHPUnit или чем-то еще?
Приветствия.
Если ваша цель — 100% охват, вам придется пойти по пути потенциально «чрезмерной оптимизации» вашего кода ради него. В этом случае это не было бы слишком большим хитом все же.
Один из вариантов заключается в том, чтобы абстрагировать строку шифрования в ее собственный частично смоделируемый метод, однако, делая это (и сообщая PHPUnit, что он будет возвращать), вы фактически просто проверяете, что исключение может быть выдано (в буквальном смысле).
Семантически говоря, методы получения / установки обычно бывают публичными, хотя это не строго соблюдается никакими органами. Я полностью понимаю, почему ты не хочешь getPrivateKey
как часть вашего API, но вы мог целесообразно добавить setPrivateKey
метод к вашему общедоступному API — это решит вашу проблему с модульным тестированием:
# File: YourClass
public function setPrivateKey(string $key) : YourClass
{
$this->privateKey = $key;
return $this;
}
Затем:
# File: YourClassTest
/**
* @expectedException RuntimeException
* @expectedExceptionMessage Encryption failed: could not generate a random key.
*/
public function testGenerateRandomKeyThrowsExceptionWhenCannotEncrypt()
{
$class = new YourClass;
$class->setPrivateKey('highly-unlikely-to-be-a-valid-private-key');
$class->generateRandomKey();
}
Конечно, делая это, вы сталкиваетесь с аргументом, что «вы не должны тестировать код, который вам не принадлежит», то есть openssl
метод. Это компромисс, который вы сделаете, чтобы достичь 100% покрытия, если это ваша цель.
Тебе нужно заглушить openssl_public_encrypt
вернуть ложь.
Предполагая ваш generateRandomKey
метод принадлежит классу StephanV
тест может выглядеть так:
namespace Tests;
function openssl_public_encrypt()
{
return false;
}
class StephanVTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException \RuntimeException
*/
public function testGenerateRandomKeyThrowsException()
{
$cut = new StephanV;
$cut->generateRandomKey();
}
}