6
votes

Phpsorm, phpunit et setcookie

J'essaie de faire des tests unitaires à l'aide d'une fonction Setcookie () dans un très bon phpstorme IDE Phpstorm. Mais je reçois une erreur suivante à chaque fois:

/usr/bin/php /tmp/phpunit.php -config /var/www/.../protected/tests/phpunit.xml d /var/www/.../protected/tests/unit/user


2 commentaires

duplicaillier possible de Test de l'unité PHPUnit avec des éléments qui doivent Envoyer des en-têtes


J'utilisais ce qui suit: PHPUNIT --STDERR qui a fonctionné lors de l'utilisation de Setcookie. Stackoverflow.com/questions/9745080/...


4 Réponses :


6
votes

Une solution possible autour de cela est d'utiliser un remplacement «simulé» pour la fonction Setcookie () .

Il s'agit d'une technique courante dans les tests unitaires, où vous souhaitez tester quelque chose qui s'appuie sur une classe ou une fonction externe que vous ne souhaitez pas affecter le test actuel.

La manière de le faire serait de créer une définition de fonction de stub pour setcookie () dans votre code de test unitaire. Cela serait alors appelé lors du test au lieu de la fonction réelle Setcookie () . Exactement comment vous implémentez cette fonction de talon vous appartient et dépend de ce que votre code l'utilise pour.

Le problème majeur que vous aurez avec cette approche est que PHP ne vous permet pas de remplacer les fonctions existantes par défaut - si vous essayez ceci sur une installation PHP standard, vous obtiendrez "Erreur: la fonction ne peut pas être redéclamé" .

La solution à ce problème est PHP's Extension Runkit , qui est explicitement conçue pour ce type de test , et vous permet de renommer une fonction existante , y compris intégrée.

Si vous configurez l'installation PHP dans votre environnement de test pour inclure l'extension Runkit, vous pourrez effectuer ce type de test.

espère que cela aide.


4 commentaires

Merci beaucoup pour votre réponse, Spudley! C'est une très bonne idée. Je vais essayer de runkit sur mon environnement de test bientôt.


Si vous ne voulez pas ou ne pouvez pas utiliser Runkit (même si vous le pouvez), je vous recommande de créer une classe qui encapsule toute la manipulation des cookies. Vous pouvez ensuite créer un objet simulé pour cette classe pour éviter d'appeler setcookie () entièrement.


Merci pour votre réponse, David! Il semble que votre point soit encore plus applicable. Mais j'ai déjà réussi avec Runkit en redéfinissant Setcookie () comme ceci: runkit_function_redefine ('setcookie', '$ nom = null, $ path = null, $ path = null, $ path = null, $ path = null, $ path = null, $ path = null, $ PATH = , $ domaine = null, $ sécurisé = null, $ httponly = null ',' ');


Les liens sont 404.



6
votes

J'ai trouvé une solution plus simple. Considérez cette classe:

class CookieTest
{
    /**
     * @runInSeparateProcess
     */
    function test_set()
    {
        $cookie = new Cookie;
        $this->assertTrue($cookie->set('mycookie', 'myvalue');
    }
}


2 commentaires

Le test échouera parce que Cookie :: Set Retours Void.


@Johnlinhart Cela ne fait que supprimer l'erreur, mais la valeur n'est pas réellement définie dans le processus (processus séparé). Donc, vous ne pouvez pas tester le code et affirmer $ _Cookie ['mycookie'] == 'myvalue'. Vous obtiendrez une erreur d'index non définie.



-2
votes

au lieu d'essayer de définir des en-têtes de cookie réels (qui échouera parce que le contenu a déjà été envoyé); À des fins de test, vous pouvez simplement définir le cookie Superglobal explicitement:

$_COOKIE['mycookie']=myvalue';


1 commentaires

Downvothed cela puisque ce n'était pas une solution de travail, mais ne peut pas annuler cela maintenant. En fait, cela fonctionne pour moi maintenant en combinaison avec le @RuninSeparateProcess annotation. Sinon, l'erreur "en-tête déjà envoyée" est toujours apparue.



0
votes

Solution de contournement d'une autre sans créer de classe de proxy et se moquer de celui-ci, mais nécessite une modification du niveau de code de travail.

function setTestableCookie(string $key, $value): void
{
    $_COOKIE[$key] = $value;

    if (headers_sent() === false) {
        setcookie(
          $key,
          $value,
          ... other cookie params ...
        );
    }
}


0 commentaires