3 votes

dans le test unitaire, mettre la valeur de l'objet fantaisie en argument (pass-by-reference)

J'ai une méthode :

-(void)startTaskForResult:(long long*)result {
  ...
}

La fonction que je veux tester en unité invoque la fonction ci-dessus :

-(void)doWork {
 long long result = 0;
 [self startTaskForResult:&result];
}

J'utilise OCMock pour faire des tests unitaires. Dans mon scénario de test, je veux définir l'option result à une valeur simulée, par exemple 100, sans se soucier de l'implémentation réelle de la fonction -(void)startTaskForResult:(long long*)result .

J'ai essayé de la manière suivante :

-(void)testDoWork{
// try to set 100 to argument 'result'
OCMStub([classToTest startTaskForResult:[OCMArg setToValue:OCMOCK_VALUE((long long){100})]]);
// run the function, but it doesn't use mocked value 100 for argument 'result'
[classToTest doWork];
...
}

Mais, lorsque j'exécute mon test, il n'utilise pas la valeur simulée 100 comme argument. result . Quelle est la bonne façon de définir la valeur de l'objet fictif comme argument dans mon cas ?

2voto

Petro Korienev Points 1900

Quelques points pour répondre à votre question :

Code pour votre problème :

- (void)testDoWork 
{
    id mock = OCMPartialMock(classToTest)
    OCMStub([mock startTaskForResult:[OCMArg setToValue:OCMOCK_VALUE((long long){100})]]).andForwardToRealObject;
    // set your expectation here
    [classToTest doWork];
}
  1. Pour résoudre votre problème particulier :

    • Votre objet doit être un mock partiel
    • Votre méthode doit être stubée (vous l'avez fait).
    • Votre stub devrait être transféré vers un objet réel (je suppose que vous avez besoin de la méthode startTaskForResult: à appeler)
  2. Cependant, vous rencontrez des problèmes parce que vous utilisez une mauvaise approche pour tester ;

Il y a 3 stratégies les plus courantes pour écrire des tests unitaires :

  1. Arrangez- Agissez-Assurez utilisé pour tester méthodes
  2. Given-When-Then utilisé pour tester fonctions
  3. Setup-Record-Verify utilisé pour tester les effets secondaires. Cela nécessite généralement l'utilisation de simulateurs.

Donc :

  • Si vous voulez tester que startTaskForResult: renvoie une valeur particulière - vous devez appeler cette méthode et attendre la valeur de retour (ce n'est pas votre cas, le type de retour de la méthode est void).
  • Si la méthode change l'état de l'objet, il faut s'attendre à ce que l'état change, comme la valeur d'une propriété, par exemple.
  • Si l'appel de doWork a pour effet secondaire d'appeler startTaskForResult: vous devez le stuber et attendre son appel, comme je l'ai écrit dans le code ci-dessus. Cependant, ( !!!) mais il ne faut pas s'attendre à des choses comme ça. Ce n'est pas un type de comportement qui a beaucoup de sens pour être testé, car il s'agit de détails d'implémentation internes à la classe. Un cas possible, lorsque les deux méthodes sont publiques et qu'il est explicitement indiqué dans le contrat de classe, qu'une méthode doit en appeler une autre avec une certaine configuration préliminaire. Dans ce cas, on s'attend à ce que l'appel de la méthode soit accompagné d'un état ou d'arguments.

Pour que le code de votre application soit testable, vous devez continuellement le remanier. Certains codes ne sont pas testables, il est probablement préférable d'adopter le code de l'application plutôt que d'essayer de le couvrir de tests de toute façon. Vous perdez l'objectif initial des tests - la sécurité du remaniement et le faible coût des modifications.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X