2017-02-21 45 views
2

У меня есть пример, как это, который основан на генераторе ключа 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 или чего-то еще?

Cheers.

ответ

1

Если 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% -ного покрытия, если это ваша цель.

+1

Кстати - если ваш getPrivateKey делает его собственная проверка и бросает свое исключение вам нужно частично издеваться так, это не в вашем тесте для generateRandomKey –

0

Чтобы вернуть false, вам необходимо закодировать 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(); 
    } 
} 
+0

Проблема заключается в том, что вы в основном проверяете только логику, в которой говорится: «Если false является ложным, а затем генерирует исключение» –

+0

@RobbieAverill, я тестирую, что 'generateRandomKey' генерирует ожидаемый исключение, когда функция native возвращает false. –

+0

Возможно, это правда, да - с точки зрения публичного API, и это то, что вы должны тестировать в конце дня. Я полагаю, что аналогия должна быть проверкой конечного результата, а не пути для его получения (если только путь не является также public API) –

 Смежные вопросы

  • Нет связанных вопросов^_^