J'ai vérifié le [jmockit] de Java (https://qiita.com/mima_ita/items/4e48a24561960851e3fa) avant, mais cela ne correspond pas un peu, c'est donc un mémo quand j'ai vérifié Mockito et Powermock en tant que Plan B.
Mockito https://site.mockito.org/
Mockito JavaDoc https://javadoc.io/doc/org.mockito/mockito-core/3.1.0/org/mockito/Mockito.html
Powermock https://github.com/powermock/powermock/
** Environnement de vérification ** java version "1.8.0_202" Eclipse IDE for Enterprise Java Developers. Version: 2019-03 (4.11.0) Build id: 20190314-1200 JUnit4 mockito-2.23 powermock-mockito2-2.0.2
Mockito est une bibliothèque qui fournit une maquette à utiliser lors de l'écriture de code de test. En guise de limitation, vous ne pouvez pas vous moquer des constructeurs, des méthodes statiques ou des méthodes privées.
PowerMock étend à la fois EasyMock et Mockito avec la possibilité de simuler des méthodes statiques, finales et même privées. Il est possible de travailler en combinaison avec Mockito.
Cette fois, j'ai téléchargé et utilisé "powermock-mockito2-junit-2.0.2.zip" à partir de ce qui suit. https://github.com/powermock/powermock/wiki/Downloads
De plus, dans cet environnement, une erreur s'est produite lors de l'exécution à moins que le Jar suivant n'ait été obtenu et référencé séparément. ・ Byte-buddy-1.9.10.jar ・ Byte-buddy-agent-1.9.10.jar https://howtodoinjava.com/mockito/plugin-mockmaker-error/
L'exemple ci-dessous est un exemple de création d'un stub qui renvoie une valeur fixe lorsqu'un argument spécifique est passé à la méthode fictive.
package powermockTest;
import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class Test001 {
class ClassA {
public int testInt(int x, int y) {
return x + y;
}
}
@Test
public void testWhen1() {
ClassA mockedA = mock(ClassA.class);
when(mockedA.testInt(5, 6)).thenReturn(99);
//Résultat spécifié par simulation
assertEquals(99, mockedA.testInt(5, 6));
//Résultats débloqués
assertEquals(0, mockedA.testInt(5, 7));
}
}
Les paramètres spécifiés lors de la simulation peuvent utiliser des correspondances d'arguments ainsi que des valeurs fixes. Dans l'exemple ci-dessous, vous pouvez utiliser anyInt () au lieu d'une valeur fixe pour accepter n'importe quel entier.
@Test
public void testWhen2() {
ClassA mockedA = mock(ClassA.class);
//Les conditions peuvent être spécifiées à l'aide du matcher d'arguments.
//Voir ci-dessous pour d'autres matchers d'argument
// https://javadoc.io/static/org.mockito/mockito-core/3.1.0/org/mockito/ArgumentMatchers.html
when(mockedA.testInt(anyInt(), anyInt())).thenReturn(99);
//Résultat spécifié par simulation
assertEquals(99, mockedA.testInt(5, 6));
assertEquals(99, mockedA.testInt(5, 7));
}
Vous pouvez également utiliser les concordants d'arguments suivants https://javadoc.io/static/org.mockito/mockito-core/3.1.0/org/mockito/ArgumentMatchers.html
Notez que vous ne pouvez pas utiliser de correspondance d'arguments uniquement pour certains des arguments d'une méthode comportant plusieurs arguments. Utilisez le matcher d'arguments pour tous les arguments. Si vous souhaitez utiliser une valeur littérale, l'implémentation est la suivante.
@Test
public void testWhen3() {
//Si vous utilisez un matcher d'arguments, tous les arguments doivent être fournis par le matcher.
/* eq(5)Si vous spécifiez 5 sans utiliser, l'erreur suivante se produit.
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
*/
ClassA mockedA = mock(ClassA.class);
when(mockedA.testInt(eq(5), anyInt())).thenReturn(99);
//Résultat spécifié par simulation
assertEquals(99, mockedA.testInt(5, 6));
assertEquals(99, mockedA.testInt(5, 7));
//Résultats débloqués
assertEquals(0, mockedA.testInt(6, 7));
}
Dans jmockit, s'il existe une classe simulée à l'aide de @Mocked, toutes les instances créées pendant la période de test seront simulées. mockito ne fait pas ce qui suit:
@Test
public void testWhen4() {
ClassA mockedA = mock(ClassA.class);
when(mockedA.testInt(5, 6)).thenReturn(99);
//Résultat spécifié par simulation
assertEquals(99, mockedA.testInt(5, 6));
//Contrairement à jmockit, cela n'affecte pas la prochaine instance créée.
ClassA objA = new ClassA();
assertEquals(11, objA.testInt(5, 6));
}
Pour renvoyer un autre résultat avec le même argument, implémentez ce qui suit.
//Comment renvoyer des résultats différents avec les mêmes arguments
@Test
public void testWhen5() {
ClassA mockedA = mock(ClassA.class);
when(mockedA.testInt(5, 6))
.thenReturn(99)
.thenReturn(100);
//Résultat spécifié par simulation
assertEquals(99, mockedA.testInt(5, 6));
assertEquals(100, mockedA.testInt(5, 6));
assertEquals(100, mockedA.testInt(5, 6));
//Une autre façon d'écrire
when(mockedA.testInt(1, 2)).thenReturn(10,20,30);
assertEquals(10, mockedA.testInt(1, 2));
assertEquals(20, mockedA.testInt(1, 2));
assertEquals(30, mockedA.testInt(1, 2));
assertEquals(30, mockedA.testInt(1, 2));
}
Si vous implémentez ce qui suit, il sera écrasé par le contenu décrit à la fin.
when(mockedA.testInt(5, 6)).thenReturn(99); //Ceci est ignoré
when(mockedA.testInt(5, 6)).thenReturn(100);
Pour générer une exception avec une méthode simulée, implémentez ce qui suit.
@Test
public void testWhen6() {
ClassA mockedA = mock(ClassA.class);
doThrow(new IllegalArgumentException("test")).when(mockedA).testInt(5, 6);
try {
//Obtenez la deuxième valeur définie dans les attentes
mockedA.testInt(5, 6);
fail();
} catch (IllegalArgumentException ex) {
assertEquals("test", ex.getMessage());
}
}
@Test
public void testWhen6_2() {
ClassA mockedA = mock(ClassA.class);
when(mockedA.testInt(5, 6)).thenThrow(new IllegalArgumentException("test"));
try {
//Obtenez la deuxième valeur définie dans les attentes
mockedA.testInt(5, 6);
fail();
} catch (IllegalArgumentException ex) {
assertEquals("test", ex.getMessage());
}
}
Les talons de l'interface de réponse (https://javadoc.io/static/org.mockito/mockito-core/3.1.0/org/mockito/stubbing/Answer.html) sont autorisés.
@Test
public void testWhen7() {
ClassA mockedA = mock(ClassA.class);
when(mockedA.testInt(5, 6)).thenAnswer(
new Answer<Integer>() {
public Integer answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
System.out.println("getArguments----------------");
for (Object arg : args) {
System.out.println(arg);
}
//Doublez la valeur du traitement réel
return (int)invocation.callRealMethod() * 2;
}
}
);
//Résultat spécifié par simulation
assertEquals(22, mockedA.testInt(5, 6));
}
InvocationOnMock est disponible pour la méthode de rappel. Il est possible d'obtenir les arguments passés via InvocationOnMock, la méthode simulée, et d'exécuter la méthode réelle.
Il est possible de créer une maquette avec une ligne avec l'implémentation suivante.
@Test
public void testWhen8() {
ClassA mockedA = when(mock(ClassA.class).testInt(anyInt(), anyInt())).thenReturn(99).getMock();
assertEquals(99, mockedA.testInt(5, 6));
}
En utilisant Spy, il est possible de se moquer uniquement d'une partie de l'objet. L'exemple ci-dessous renvoie une valeur simulée uniquement lorsqu'il est exécuté avec des arguments spécifiques. À part cela, le résultat de l'exécution de la méthode réelle est renvoyé.
@Test
public void testSpy1() {
ClassA objA = new ClassA();
ClassA spyA = Mockito.spy(objA);
when(spyA.testInt(5, 6)).thenReturn(99);
//Résultat spécifié par simulation
assertEquals(99, spyA.testInt(5, 6));
//Résultats débloqués
//La vraie chose est appelée différemment du temps de la simulation.
assertEquals(12, spyA.testInt(6, 6));
}
Vous pouvez utiliser verify pour vérifier comment la méthode simulée a été exécutée.
@Test
public void testVerify1() {
ClassA mockedA = mock(ClassA.class);
mockedA.testInt(5,6);
mockedA.testInt(3,4);
//Assurez-vous que la méthode suivante est exécutée(Ne pas vérifier la commande)
verify(mockedA).testInt(3,4);
verify(mockedA).testInt(5,6);
}
fois/ [jamais](https: // javadoc. io /static/org.mockito/mockito-core/3.1.0/org/mockito/Mockito.html#never--)/[atLeastOnce](https://javadoc.io/static/org.mockito/mockito-core /3.1.0/org/mockito/Mockito.html#atLeastOnce--)/[atMostOnce](https://javadoc.io/static/org.mockito/mockito-core/3.1.0/org/mockito/Mockito. html # atMostOnce--) / atLeast/[atMost] Il est possible de vérifier le nombre de fois qu'il a été exécuté par (https://javadoc.io/static/org.mockito/mockito-core/3.1.0/org/mockito/Mockito.html#atMost-int-).
@Test
public void testVerify2() {
ClassA mockedA = mock(ClassA.class);
mockedA.testInt(5,6);
mockedA.testInt(3,4);
//2 fois testInt(?,?)Est en cours d'exécution
verify(mockedA, times(2)).testInt(anyInt(),anyInt());
// testInt(1,1)Assurez-vous qu'il ne fonctionne pas
verify(mockedA, never()).testInt(1,1);
}
En utilisant [inOrder](https://javadoc.io/doc/org.mockito/mockito-core/3.1.0/org/mockito/Mockito.html#inOrder-java.lang.Object ...-) Il est possible de vérifier l'ordre d'exécution des méthodes.
class T1 {
void t1(String a) {
}
}
class T2 {
void t2(String a) {
}
}
@Test
public void testVerify3() {
T1 mocked = mock(T1.class);
mocked.t1("first");
mocked.t1("second");
//Vérifier, y compris la commande
InOrder order = inOrder(mocked);
order.verify(mocked).t1("first");
order.verify(mocked).t1("second");
}
@Test
public void testVerify4() {
//Il est également possible de vérifier l'ordre d'exécution de plusieurs objets
T1 t1 = mock(T1.class);
T2 t2 = mock(T2.class);
t1.t1("call 1");
t2.t2("call 2");
t1.t1("call 3");
t2.t2("call 4");
//Vérifier, y compris la commande
InOrder order = inOrder(t1, t2);
order.verify(t1).t1("call 1");
order.verify(t2).t2("call 2");
order.verify(t1).t1("call 3");
order.verify(t2).t2("call 4");
}
La méthode finale ne peut pas être simulée avec les paramètres par défaut. Pour activer la simulation de la méthode finale, vous devez créer le fichier suivant.
/mockito-extensions/org.mockito.plugins.MockMaker
mock-maker-inline
class ClassB {
final public int testFinal(int x, int y) {
return x + y;
}
}
@Test
public void testFinal1() {
//les méthodes finales ne peuvent pas être simulées par défaut
// /mockito-extensions/org.mockito.plugins.Créez un fichier MockMaker et
//Vous devez saisir les caractères suivants
// mock-maker-inline
ClassB mockedB = mock(ClassB.class);
when(mockedB.testFinal(5, 6)).thenReturn(99);
//Résultat spécifié par simulation
assertEquals(99, mockedB.testFinal(5, 6));
}
Lorsque vous utilisez PowerMock, ajoutez l'annotation suivante à la classe. ・ @RunWith (PowerMockRunner.class) ・ @PrepareForTest ({ZZZZ.class, XXX.class})
PrepareForTest doit être une classe qui doit être manipulée au niveau du code d'octet pendant le test. Lors de la simulation de méthodes statiques, de constructeurs et de méthodes privées.
package powermockTest;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest({Calendar.class, java.lang.Math.class})
public class Test002 {
}
Dans l'exemple ci-dessous, la méthode privée test1 est simulée et il est confirmé que la valeur simulée est renvoyée lorsqu'elle est exécutée via test2.
class ClassPrivate {
private int test1(int x, int y) {
return x + y;
}
public int test2(int x) {
return test1(x, x) + 1;
}
}
@Test
public void testPrivate1() {
ClassPrivate objA = new ClassPrivate();
ClassPrivate spyA = PowerMockito.spy(objA);
PowerMockito.when(spyA.test1(5, 5)).thenReturn(99);
//Résultat spécifié par simulation
assertEquals(100, spyA.test2(5));
assertEquals(99, spyA.test1(5,5));
}
L'exemple ci-dessous est un exemple simulé de java.lang.Math.random.
//Un exemple de moquerie aléatoire
@Test
public void testStatic1() {
//Veuillez définir les éléments suivants dans la classe
// @PrepareForTest({ java.lang.Math.class})
PowerMockito.mockStatic(java.lang.Math.class);
PowerMockito.when(java.lang.Math.random()).thenReturn(1.5);
assertEquals(1.5, java.lang.Math.random(), 0.1);
}
Si la méthode statique peut être moquée, l'heure actuelle peut être déguisée en heure convenable.
//Exemple de moquerie de l'heure actuelle
@Test
public void testStatic2() {
//Veuillez définir les éléments suivants dans la classe
// @PrepareForTest({ Calendar.class})
Calendar cal = Calendar.getInstance();
cal.set(2018, 1, 25, 23, 32, 30);
cal.set(Calendar.MILLISECOND, 0);
PowerMockito.mockStatic(Calendar.class);
PowerMockito.when(Calendar.getInstance()).thenReturn(cal);
Calendar c = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
assertEquals("20180225233230000", sdf.format(c.getTime()));
}
Utilisez PowerMockito.whenNew pour simuler l'instance créée dans la méthode.
class classA {
public String getA() {
return "getA";
}
}
class classB {
public String hoge(String x) {
return x + (new classA()).getA();
}
}
//Mock l'instance pour simuler l'objet utilisé dans la méthode test
@Test
public void testInner() throws Exception {
classA mockedA = Mockito.mock(classA.class);
when(mockedA.getA()).thenReturn("abc");
PowerMockito.whenNew(classA.class).withNoArguments().thenReturn(mockedA);
classB obj = new classB();
assertEquals("testabc", obj.hoge("test"));
}
Je pense qu'il existe de nombreux cas d'utilisation et que le faible coût d'apprentissage a un avantage sur JMockit. De plus, il semble que la mesure de couverture qui existait dans JMockit ne puisse pas être effectuée.
Recommended Posts