Comment se moquer de membre statique des variables
J'ai une classe ClassToTest qui a une dépendance sur ClassToMock.
public class ClassToMock {
private static final String MEMBER_1 = FileReader.readMemeber1();
protected void someMethod() {
...
}
}
L'unité de test pour ClassToTest.
public class ClassToTestTest {
private ClassToMock _mock;
@Before
public void setUp() throws Exception {
_mock = mock(ClassToMock.class)
}
}
Lorsque la maquette est appelée dans la méthode setUp (), FileReader.readMemeber1(); est exécuté. Est-il un moyen pour éviter cela? Je pense que d'une façon consiste à initialiser la MEMBER_1 à l'intérieur d'une méthode. D'autres alternatives?
Merci!
Je pense qu'il y a des outils qui vous permettent de maquette statique des variables, mais elles impliquent beaucoup de hacks. Parce que cette classe est difficile à tester, écouter ce que les tests sont à même de vous dire, et faire de votre classe plus faiblement couplés à
Question: Est votre préoccupation juste que
Oui. Je ne veux pas FileReader.readMember à être exécuté. C'est une autre dépendance.
- Je ajouter une autre étape dans ma réponse, ce qui devrait résoudre votre problème.
FileReader
.Question: Est votre préoccupation juste que
FileReader.readMember
est exécuté (c'est à dire que les tests unitaires ne devrait pas frapper le système de fichiers), ou êtes-vous vouloir aussi les différents tests pour avoir des valeurs différentes pour MEMBER_1?Oui. Je ne veux pas FileReader.readMember à être exécuté. C'est une autre dépendance.
- Je ajouter une autre étape dans ma réponse, ce qui devrait résoudre votre problème.
OriginalL'auteur pkrish | 2012-12-05
Vous devez vous connecter pour publier un commentaire.
Votre
ClassToMock
étroitement couplé avecFileReader
, c'est pourquoi vous n'êtes pas en mesure de tester/en moquer. Au lieu de l'aide de l'outil de hack de l'octet de code de sorte que vous pouvez s'en moquer. Je vous suggère de faire quelques simples refactorings de briser la dépendance.L'étape 1. Encapsuler Les Références Globales
Cette technique est également introduite dans Michael Plumes livre merveilleux : Travailler Efficacement avec le Code existant.
Le titre assez bien l'auto expliqué. Au lieu de faire directement référence à une variable globale, vous l'encapsuler dans une méthode.
Dans votre cas,
ClassToMock
peut être remaniée en ceci :ensuite, vous pouvez facilement en utilisant Mockito, à se moquer degetMemberOne()
.Mis à JOUR Vieux Étape 1 ne peut pas garantir
Mockito
se moquer en toute sécurité, siFileReader.readMemeber1()
jeter l'exception, alors que le test sera failled lamentablement. Je suggère donc d'ajouter une autre étape de travail autour d'elle.L'étape 1.5. ajouter Setter et Paresseux Getter
Puisque le problème est
FileReader.readMember1()
sera invoqué dès queClassToMock
est chargé. Nous avons de retard. Donc, nous faisons de la lecture d'appelFileReader.readMember1()
paresseusement, et d'ouvrir un setter.Maintenant, vous devriez pouvoir faire un faux
ClassToMock
même sansMockito
. Toutefois, cela ne devrait pas être l'état final de votre code, une fois que vous avez votre test prêt à l'emploi, vous devez continuer à l'Étape 2.L'étape 2. Dépendance À L'Injection
Une fois que vous avez votre test prêt à l'emploi, vous devez refactoriser le code encore plus. Maintenant, au Lieu de la lecture de la
MEMBER_1
par lui-même. Cette classe doit recevoir leMEMBER_1
du monde extérieur à la place. Vous pouvez soit utiliser un setter ou le constructeur pour le recevoir. Ci-dessous est le code qui utilisent setter.Ces deux étapes refactorings sont vraiment facile à faire, et vous pouvez le faire même sans test à la main. Si le code n'est pas complexe, il vous suffit de faire l'étape 2. Ensuite, vous pouvez facilement tester
ClassToTest
Mise à JOUR 12/8 : répondre au commentaire
Voir mon autre réponse à cette question.
En fait, j'ai trouver etape 1 ne peut pas garantir
Mocktio
maquette correctement. - Je ajouter une autre étape pour contourner le problème.Que faire si FileReader est quelque chose de très basique comme l'exploitation forestière, qui doit être présent dans chaque classe. Suggérez-vous que j'ai suivi la même démarche?
Dans ce cas, je voudrais suggérer d'autres. Veuillez lire mon l'autre réponse.
OriginalL'auteur Rangi Lin
Mise à JOUR 12/8 : répondre au commentaire
Il dépend.
Il y a quelque chose que vous voudrez peut-être penser avant de faire un énorme refactoriser comme ça.
Si je bouge
FileReader
à l'extérieur, puis-je avoir une personne de la classe qui peut lire à partir du fichier et de fournir le résultat de chaque classe, qui en a besoin ?À côté faire des classes plus facile à tester, puis-je obtenir un autre avantage ?
Ai-je le temps ?
Si l'une des réponses est "NON", alors vous devriez mieux de ne pas.
Cependant, on peut toujours rompre la dépendance entre toutes les classes et
FileReader
avec un minimum de modifications.De vos questions et commentaires, je suppose que votre système à l'aide de
FileReader
de référence mondiale pour la lecture des choses à partir d'un fichier de propriétés, puis les fournir au reste du système.Cette technique est également introduite dans Michael Plumes livre merveilleux : Travailler Efficacement avec le Code existant, encore une fois.
L'étape 1. Délégué
FileReader
méthodes statiques pour l'exemple.Changement
À
En faisant cela, des méthodes statiques dans
FileReader
n'ont désormais plus de connaissances sur la façon degetMemberOne()
L'étape 2. Extrait de l'Interface à partir de
FileReader
Nous avons extrait toutes les méthode à
AppProperties
, et l'instance statique dansFileReader
maintenant à l'aide deAppProperties
.L'étape 3. Statique setter
Nous avons ouvert une couture dans FileReader. En faisant cela, on peut changer instance sous-jacente dans
FileReader
et il n'y aurait jamais d'avis.L'étape 4. Nettoyer
Maintenant
FileReader
ont deux responsabilités. L'un est de lire des fichiers et de fournir conséquent, un autre est de fournir une référence pour le système.Nous pouvons séparer d'eux et de leur donner un bon nommage. Voici le résultat :
FIN.
Après ce remaniement, à chaque fois que vous voulez tester. Vous pouvez définir une maquette
AppProperties
àGlobalAppProperties
Je pense que cette factorisation serait mieux si tout ce que vous voulez faire est de briser les mêmes globale de la dépendance dans de nombreuses classes.
OriginalL'auteur Rangi Lin