Se moquant privé méthodes utilisées dans la méthode publique avec PowerMock, Mockito, et TestNG
Je veux écrire un test unitaire pour une classe que j'ai. Cette classe possède une méthode publique, et à l'intérieur de la méthode publique il y a des appels à des méthodes privées dans la même classe. Je veux moquer des appels à ces méthodes privées. La classe est similaire à ceci:
public class SomeClass {
public int somePublicMethod(int num) {
int num2 = somePrivateMethod1(num);
int num3 = somePrivateMethod2(num);
return num2 + num3;
}
private int somePrivateMethod1(int num) {
return 2*num;
}
private int somePrivateMethod2(int num) {
return 3*num;
}
}
Pour mon unité de test, je suis en train d'utiliser PowerMock avec Mockito et TestNG. Voici ma tentative de test qui teste somePublicMethod:
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.spy;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.Assert;
import org.testng.annotations.Test;
@PrepareForTest(SomeClass.class)
public class SomeClassTest {
@Test
public void testSomePublicMethod() throws Exception {
int num = 4;
SomeClass someClassSpy = spy(new SomeClass());
doReturn(8).when(someClassSpy, "somePrivateMethod1", num);
doReturn(12).when(someClassSpy, "somePrivateMethod2", num);
int result = someClassSpy.somePublicMethod(num);
Assert.assertEquals(result, 20);
}
}
Lorsque j'exécute ce test, j'obtiens une exception et quelques conseils:
FAILED: testSomePublicMethod
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:31)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
J'ai regardé quelques exemples en ligne, mais je n'ai pas trouvé un qui utilise PowerMock avec Mockito et TestNG spécifiquement à faire ce que je veux. Quelqu'un peut-il me donner quelques conseils sur ce que j'ai pu faire différemment?
OriginalL'auteur Thomas | 2012-05-09
Vous devez vous connecter pour publier un commentaire.
Je ne pense pas que ce soit un problème avec PowerMock. Il semble comme il devrait fonctionner très bien comme il est. Je me demande si il y a un problème avec TestNG interagir avec PowerMock?
Je n'ai aucune expérience avec TestNG, j'ai donc essayé de lancer la classe JUnit.
SomeClass
a été laissé tel quel,SomeClassTest
a été très peu modifié pour utiliser JUnit:Le test passe.
Avez-vous besoin de spécifier un
PowerMockRunner.class
à l'aide de@RunWIth
ou d'une même annotation, comme avec JUnit? Si je supprime cette annotation, j'obtiens le même message d'erreur que vous avez posté.EDIT:
Selon ce lien:
http://code.google.com/p/powermock/wiki/TestNG_usage
Vous devez dire à TestNG pour utiliser le PowerMock objet d'usine. Pour ce faire par programme, ajoutez une méthode de ce genre pour votre classe de test:
ou à être sur le côté sûr, vous pouvez également étendre à partir de la PowerMockTestCase:
OriginalL'auteur Tom Tresansky
Vous ne pouvez pas le faire par ce moyen. Avez-vous essayé d'utiliser la réflexion?
Par l'aide de la réflexion, vous pouvez vous moquer des méthodes privées en se moquant de l'invoquer des méthodes, ou plus simple: vous pouvez la changer en public temporaire, puis après le test (peut-être dans le démontage) - vous pouvez le modifier à privé.
Espérons que cette aide.
même si nous pouvions utiliser la réflexion, mais il n'est pas recommandé. Comme vous le savez, la méthode doit être appelée par un de vos méthodes publiques de toute façon, il est donc préférable de tester tout public à partir de la méthode.
Lorsque vous êtes à la mise en œuvre quoi que ce soit, assurez-vous simplement que vous êtes en train de rédiger un code de tests. Vous pouvez effectuez une recherche à partir de google pour "Testable vs Invérifiables code", vous trouverez quelques-unes des meilleures pratiques et des défauts à éviter.
Oui la méthode privée est appelé méthode publique, mais le problème est la méthode privée donneront toujours une exception dans l'environnement de test, c'est la méthode pour obtenir DB connexion.
L'isolement est la chose la plus importante dans les tests unitaires, vous avez besoin de l'isoler d'autres choses, comme d'autres services, d'autres classes... bien sûr, de l'isoler de l'environnement (base de données)
OriginalL'auteur nnhthuan
Je pense que vous êtes hiting un Mockito limite ici. Dans des cas similaires, j'utilise Powermock méthode de remplacement ou de, déclarer la cible de la méthode d'protégés et de le remplacer lors de la construction de la classe testée instance.
Espérons que cela aide.
OriginalL'auteur