Position actuelle: Accueil> Derniers articles> Comment se moquer du retard du temps_nanosleep dans les tests unitaires

Comment se moquer du retard du temps_nanosleep dans les tests unitaires

gitbox 2025-05-26

Lors de l'exécution de tests unitaires PHP, le code impliquant des retards (tels que Time_nanosleep ) entraîne souvent un ralentissement des tests et augmente le temps d'exécution des processus CI / CD. De plus, le test lui-même s'appuiera également sur le temps réel, réduisant la prévisibilité et la stabilité du test. Pour améliorer l'efficacité et maintenir la pureté des tests, nous avons généralement besoin de fonctions de retard comme "simulé".

Cet article expliquera comment simuler le comportement de la fonction Time_nanosleep dans les tests unitaires en PHP sans vraiment introduire de retards.

Exemple de code d'arrière-plan

Imaginez que nous ayons une classe de service, et les méthodes de cette classe utiliseront Time_nanosleep pour effectuer des opérations de retard court:

 class TaskRunner
{
    public function runWithDelay(): string
    {
        time_nanosleep(0, 500000000); // Retard 0.5 Deuxième
        return 'done';
    }
}

Si nous testons directement la méthode, le test s'arrêtera pendant une demi-seconde, ce qui est inacceptable dans un grand nombre de scénarios de test. Nous devons trouver un moyen de "remplacer" ou de "redéfinir" Time_nanosleep .

Conseils pour la réécriture à l'aide des fonctions d'espace de noms

PHP n'a pas de fonction de fonction intégrée, mais nous pouvons utiliser le mécanisme de recherche de fonction de PHP: dans un espace de noms, si nous définissons une fonction avec le même nom que la fonction globale, les fonctions de l'espace de noms sont appelées d'abord.

Étape 1: encapsuler le code dans l'espace de noms

Nous encapsulons le code commercial dans un espace de noms, tel que Gitbox \ Runtime :

 namespace Gitbox\Runtime;

function time_nanosleep(int $seconds, int $nanoseconds)
{
    // Comportement original:Appeler des fonctions globales
    return \time_nanosleep($seconds, $nanoseconds);
}

class TaskRunner
{
    public function runWithDelay(): string
    {
        time_nanosleep(0, 500000000);
        return 'done';
    }
}

Maintenant, TaskRunner utilise Gitbox \ Runtime \ Time_nanosleep , que nous pouvons remplacer dans nos tests.

Étape 2: Réécrivez le comportement de la fonction dans les tests

Dans le fichier de test, nous définissons une fonction Time_nanosleep moquée sous le même espace de noms:

 namespace Gitbox\Runtime;

function time_nanosleep(int $seconds, int $nanoseconds)
{
    // 模拟Retard:Ne rien faire
    return true;
}

Ensuite, nous pouvons le tester comme d'habitude:

 use Gitbox\Runtime\TaskRunner;
use PHPUnit\Framework\TestCase;

class TaskRunnerTest extends TestCase
{
    public function testRunWithDelay()
    {
        $runner = new TaskRunner();
        $result = $runner->runWithDelay();

        $this->assertEquals('done', $result);
    }
}

Étant donné que nous l'emportons sur Time_nanosleep dans l'environnement de test, il n'y aura pas de véritable retard dans le test.

Utiliser l'injection de dépendance (méthode d'amélioration facultative)

Un autre moyen plus orienté objet consiste à encapsuler des opérations retardées dans une classe, et en injectant la dépendance dans l'exécuteur de la tâche, nous pouvons simuler plus de manière flexible divers comportements, tels que l'augmentation des exceptions, la simulation de blocage à long terme, etc.

 interface SleeperInterface
{
    public function sleep(): void;
}

class RealSleeper implements SleeperInterface
{
    public function sleep(): void
    {
        time_nanosleep(0, 500000000);
    }
}

class TaskRunner
{
    private SleeperInterface $sleeper;

    public function __construct(SleeperInterface $sleeper)
    {
        $this->sleeper = $sleeper;
    }

    public function runWithDelay(): string
    {
        $this->sleeper->sleep();
        return 'done';
    }
}

Dans le test, nous pouvons utiliser des classes simulées:

 class FakeSleeper implements SleeperInterface
{
    public function sleep(): void
    {
        // N'effectuez aucune action
    }
}

Comment utiliser:

 $sleeper = new FakeSleeper();
$runner = new \Gitbox\Runtime\TaskRunner($sleeper);
$this->assertEquals('done', $runner->runWithDelay());

Résumer

En PHP, le moyen le plus efficace de tester les fonctions dépendant du temps est généralement de redéfinir la fonction via l'espace de noms ou d'utiliser l'injection de dépendance. Pour les fonctions globales comme Time_nanosleep , nous vous recommandons d'utiliser des techniques de réécriture d'espace de noms et de garder la logique de test dans les limites contrôlables du projet.

De plus, l'utilisation d'interfaces et d'injection de dépendance peut rendre votre code plus flexible et testable, et adapté à des scénarios plus complexes.

Grâce à ces méthodes, vous pouvez simuler complètement les retards dans le test sans introduire des coûts en temps réel, améliorant considérablement l'efficacité des tests et la stabilité.

Pour des exemples pratiques plus pertinents, veuillez visiter https://gitbox.net .