2009-07-01 2 views
3

J'ai un module Perl que je l'ai déclaré quelques constantes:Existe-t-il un moyen de remplacer une "constante d'utilisation" Perl dans vos tests unitaires?

use constant BASE_PATH => "/data/monitor/"; 

En fonctionnement direct la constante ne changera jamais, mais je veux être en mesure de modifier dans mes tests unitaires, par exemple pour le définir sur ~/project/testdata/. Y at-il un moyen de le faire sans avoir à utiliser "non-constantes"?

Pourrais-je éventuellement utiliser Test :: MockObject sur le constant.pm?

+0

Si vous avez besoin de le changer tout au long des tests, pourquoi ne pas en faire un 'non constant'? – user105033

+0

Vous pouvez essayer le sous-programme d'importation de constante de singe. – daotoad

+0

Pourquoi feriez-vous cela au lieu d'avoir un fichier de configuration? –

Répondre

6

Lors de l'utilisation des constantes mises en œuvre comme ils sont des fonctions constantes se comporter quelque chose comme:

use subs 'BASE_PATH'; 
sub BASE_PATH() {"/data/monitor/"} 

Toute utilisation de base_path dans le programme sont inline et ne peuvent donc pas être modifiés.

Pour similaire, vous pouvez utiliser manuellement les sous-marins pragma (pour faire se comportent base_path comme fonction intégrée) et déclarer base_path en fonction standard:

use subs 'BASE_PATH'; 
sub BASE_PATH {"/data/monitor/"} 

print "BASE_PATH is ".BASE_PATH."\n"; 

*BASE_PATH = sub {"/new/path"}; 
print "BASE_PATH is ".BASE_PATH."\n"; 

Bien que la raison pour laquelle vous voulez faire I » Je ne suis pas trop sûr.

+0

N'oubliez pas de le mettre dans le bon paquet. –

1

Apparemment, si votre définition de base_path a été utilisé/compilé dans un autre sous-programme avant le test ne change (via

*BASE_PATH = sub { ... } 

ou d'autres choses) vous avez pas de solution (car lorsque le module original utilisé base_path comme une constante, il a vraiment défini une fonction inline qui était, bien, inline lorsqu'il est utilisé dans tout autre code)

+0

La seule solution consiste à exécuter la sous-routine d'importation de constante de singe. Installez un wrapper autour de l'importation de constante qui intercepte les noms de constante spécifiés à remplacer et les valeurs à appliquer. Si vous faites cela, alors seulement les sous-jacents constants surchargés seront créés et ils seront soulignés par le compilateur. Je n'ai pas le temps d'écrire quelque chose comme ça en ce moment, mais ça ne devrait pas être trop dur. – daotoad

+0

Mais dans ce cas, faire votre propre constant.pm qui ne laisse pas le sous-titre être encore mieux/plus facile, non? Mettez-le quelque part au début du chemin de la bibliothèque de test et ta-da ... – Massa

2
 
package My::Class; 

use constant BASE_PATH => "https://stackoverflow.com/a/real/value/"; 

# ..more code here.. 

1; 

maintenant dans vos tests unitaires:

 
use My::Class; 
*{My::Class::BASE_PATH} = sub { "https://stackoverflow.com/a/fake/value" }; 

# do your tests here... 
+1

Serait-ce travailler avec des sous-marins dans un module? Par exemple: '' use myModule; * {myModule} = sub {"/ a/fake/value"}; '' Si ce n'est pas le cas, existe-t-il un moyen de le faire? – GuySoft

5

Les tests révèlent souvent une inflexibilité dans la conception. C'est l'une de ces fois. Cette constante ne devrait pas être constante.

Si vous le faites pour des raisons de performance, je suis prêt à parier que cela ne fait aucune différence.