[JAVA] Essayez d'utiliser powermock-mockito2-2.0.2

introduction

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 et powermock

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/

Essayez d'utiliser

Utilisez Mockito

Utiliser le stub

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));
	}
}

Argument matcher

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));
	}

Gamme d'influence de la moquerie

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));

	}

Comment renvoyer différents résultats avec la même valeur d'argument

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);

Comment générer une exception avec une méthode simulée

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());
		}
	}

Talon de rappel

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.

Créer une maquette avec une ligne

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));
	}

Simulation partielle avec Spy

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));

	}

Vérification à l'aide de Verify

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);
	}

Vérification du nombre d'exécutions

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);
	}

Vérification de l'ordre d'exécution

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");
	}

Mocking final méthodes

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

image.png

	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));

	}

Utilisez PowerMock

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 {
}

Méthode privée moqueuse

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));

	}

Se moquer de la méthode statique

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);
	}

Usurpation d'identité de l'heure actuelle

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()));
	}

Mock l'instance créée dans la méthode

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"));

	}

Résumé

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

Essayez d'utiliser powermock-mockito2-2.0.2
Essayez d'utiliser libGDX
Essayez d'utiliser Maven
Essayez d'utiliser GraalVM
Essayez d'utiliser jmockit 1.48
Essayez d'utiliser SwiftLint
Essayez d'utiliser Log4j 2.0
Essayez d'utiliser le Framework Axon
Essayez d'utiliser l'API REST de JobScheduler
Essayez d'utiliser la méthode java.lang.Math
Essayez d'utiliser la WhiteBox de PowerMock
Essayez d'utiliser Talend Part 2
Essayez d'utiliser Talend Part 1
Essayez d'utiliser la liste F #
Essayez d'utiliser la méthode each_with_index
Essayez d'utiliser Spring JDBC
Essayez d'utiliser GloVe avec Deeplearning4j
Essayez de gratter en utilisant Java [Note]
Essayez d'utiliser Cocoa de Ruby
Essayez d'utiliser IntelliJ IDEA car vous ne devez le faire qu'une seule fois
Essayez d'utiliser Spring Boot Security
[Rails] Essayez d'utiliser le middleware de Faraday
[Traitement] Essayez d'utiliser GT Force.
[Programmation complète] §2 Essayez d'utiliser Ruby
Essayez Redmine sur le docker Mac
Essayez d'utiliser Redis avec Java (jar)
[Java] Essayez de mettre en œuvre à l'aide de génériques
Essayez d'utiliser le système de messagerie Pulsar
Essayez d'utiliser le traçage de méthode IBM Java
Essayez d'utiliser le SDK Java d'Hyperledger Iroha
[Java] Où avez-vous essayé d'utiliser java
Essayez d'utiliser le framework Java Nablarch [Application Web]
Essayez d'utiliser || au lieu de l'opérateur ternaire
Essayez HiveRunner
Essayez d'utiliser le service sur Android Oreo
Essayez d'utiliser l'API Stream en Java
Essayez Mockito
Étude de Java Essayez d'utiliser un scanner ou une carte
Essayez le sélénium
Essayez d'utiliser l'API au format JSON en Java
Essayez DbUnit
Essayez d'utiliser Spring Boot avec VS Code
Essayez d'utiliser MT Loader de Reladomo (chargeur de matrices multi-threads)
Essayez d'utiliser l'API REST de JobScheduler - implémentation Java RestClient--
Essayez d'utiliser l'API Emotion d'Android
Essayez d'utiliser la télécommande Wii en Java
Essayez Lombok
Essayez d'utiliser simple_form / modifier même les modèles enfants
Essayez d'implémenter un serveur GraphQL en utilisant grahpql-java-tools (+ kotlin)
Essayez d'utiliser Firebase Cloud Functions sur Android (Java)
Essayez d'utiliser la classe de test RestClient de JobScheduler REST-API-Java-