Comment fonctionnent les frameworks de moquerie Java?


Ce n'est PAS une question de savoir quel est le meilleur framework, etc.

Je n'ai jamais utilisé de framework moqueur et je suis un peu perplexe par l'idée. Comment sait-il comment créer l'objet simulé? Est-il fait au moment de l'exécution ou de générer un fichier? Comment savez-vous de son comportement? Et le plus important – quel est le flux de travail d'utilisation d'un tel cadre (quelle est l'étape par étape pour créer un test)?

Quelqu'un peut-il expliquer? Vous pouvez choisir le cadre que vous aimez par exemple, dites simplement ce qu'il est.

Author: Boann, 2010-06-08

5 answers

Je vais parler du framework que j'utilise ( jmock ), mais d'autres font quelque chose de très similaire.

Comment sait-il comment créer le maquette de l'objet?

Ce n'est pas le cas, vous dites au framework que vous avez besoin d'un objet fictif et vous lui donnez un type ( idéalement une interface ) de l'objet que vous souhaitez simuler. Dans les coulisses, le framework simulé utilise une combinaison de réflexion et, parfois, de réécritures de code octet pour créer un objet simulé.

Est-ce fait en cours d'exécution ou génère un fichier?

JMock le crée à l'exécution.

Comment connaissez-vous son comportement?

Les objets simulés sont assez stupides. Vous spécifiez le comportement que vous attendez d'eux.

Et surtout-qu'est-ce que le flux de travail de l'utilisation d'un tel cadre (quelle est l'étape par étape pour créer test).

Une chose très importante que framework doit fournir est la capacité de vérifier que le comportement attendu a a été observé pendant l'exécution du test.

Jmock le fait en introduisant un coureur de test spécifique qui vérifie que toutes les attentes sur tous les objets fictifs déclarés après la fin du test. Si quelque chose ne correspond pas, l'exception est levée.

Habituellement, le motif est:

  1. Acquire mock factory ( appelé Mockery dans jmock )à partir de rien ( avec un constructeur spécifique no-args ).
  2. Créer des objets simulés requis.
  3. Attente de configuration sur mock objets
  4. Appelez la méthode que vous testez, en passant des simulacres au lieu d'objets réels
  5. Si votre méthode renvoie certaines valeurs, vérifiez la valeur attendue avec des méthodes régulières assertXXX.
 9
Author: Alexander Pogrebnyak, 2010-06-07 22:30:18

Un framework moqueur supprime la redondance et le passe-partout d'un test moqueur.

Il sait créer l'objet fictif parce que vous le dites, bien sûr (sauf si vous vouliez dire autre chose avec cette question).

La façon "standard" de créer un objet fictif consiste à utiliser/abuser du java.lang.refléter.Classe Proxy pour créer une implémentation d'exécution de l'interface. Ceci est fait au moment de l'exécution. Le proxy a une limitation en ce sens qu'il ne peut pas proxy les classes concrètes. Pour accomplir la moquerie de les classes concrètes nécessitent une création de bytecode dynamique qui crée des sous-classes qui remplacent l'implémentation réelle des méthodes publiques avec essentiellement ce qui serait fait avec un proxy (enregistrez les paramètres de la méthode et renvoyez une valeur prédéterminée). Cela a une limitation en ce sens qu'il ne peut pas sous-classer les classes finales. Pour cela, vous avez des solutions comme JDave, qui (je crois, je n'ai pas confirmé cela) muck avec le classloader pour supprimer la désignation finale sur la classe avant de la charger, donc, la classe n'est pas en fait finale à l'exécution en ce qui concerne la JVM.

Le framework moqueur consiste essentiellement à capturer les paramètres et à les vérifier par rapport aux attentes prédéterminées, puis à renvoyer une valeur par défaut préconfigurée ou raisonnable. Il ne se comporte d'aucune manière particulière, ce qui est le point. Le code appelant est en cours de vérification qu'il appelle la méthode avec le paramètre correct, et peut-être comment il réagit à une valeur de retour spécifique ou jeté exception. Les effets secondaires ou les réalisations réelles de l'appel sur l'objet réel ne se produisent pas.

Voici un exemple réel d'un projet, utilisant JMock avec JUnit4. J'ai ajouté des commentaires pour expliquer ce qui se passe.

 @RunWith(JMock.class) //The JMock Runner automatically checks that the expectations of the mock were actually run at the end of the test so that you don't have to do it with a line of code in every test.
public class SecuredPresentationMapTest {

private Mockery context = new JUnit4Mockery(); //A Mockery holds the state about all of the Mocks. The JUnit4Mockery ensures that a failed mock throws the same Error as any other JUnit failure.

@Test
public void testBasicMap() {
    final IPermissionsLookup lookup = context.mock(IPermissionsLookup.class); //Creating a mock for the interface IPermissionsLookup.
    context.checking(new Expectations(){{ //JMock uses some innovative but weird double brace initialization as its standard idom.
        oneOf(lookup).canRead(SecuredEntity.ACCOUNTING_CONTRACT);
            //expect exactly one call to the IPermissionsLookup.canRead method with the the enum of ACCOUNTING_CONTRACT as the value. Failure to call the method at all causes the test to fail.
            will(returnValue(true)); //when the previous method is called correctly, return true;
    }});

    Map<String, Component> map = new SecuredPresentationMap(lookup, SecuredEntity.ACCOUNTING_CONTRACT);
    //This creates the real object under test, but passes a mock lookup rather than the real implementation.
    JLabel value = new JLabel();
    map.put("", value);
    assertThat(((JLabel) map.get("")), is(value)); //This ensures that the Map returns the value placed, which it should based on the fact that the mock returned true to the security check.
  }
}

Si la simulation passée était ignorée, le test aurait échoué. Si la carte ne parvient pas à renvoyer la valeur placée dans le test échoue (c'est la norme JUnit).

Ce qui est testé ici et dans un autre test opposé est que selon ce que le IPermissionsLookup interface dit à propos de la sécurité la carte change son comportement sur ce qui est retourné. C'est la base de la bonne affaire. L'autre test, la simulation renvoie false et quelque chose d'autre est attendu de la carte. L'utilisation de la maquette garantit que la carte repose sur la méthode IPermissionsLookup pour déterminer la posture de sécurité et ce qui est renvoyé.

 15
Author: Yishai, 2014-02-25 12:46:15

Pour une meilleure compréhension de la moquerie, vous voudrez peut-être créer votre propre objet simulé. C'est un processus assez simple - vous créez une classe qui implémente la même interface que ce dont vous vous moquez, et lui donnez le comportement dont vous avez besoin, soit en enregistrant des appels à une méthode, soit en répondant de manière définie lorsqu'elle est appelée. À partir de là, la façon dont les cadres moqueurs sont mis en place commence à avoir plus de sens.

 5
Author: Jonny Cundall, 2010-06-07 22:04:41

Je pense que La documentation d'EasyMock est un moyen get de vous aider à démarrer. Il présente de nombreux exemples faciles à saisir.

 1
Author: Bozhidar Batsov, 2010-06-07 22:00:07

EasyMock (http://easymock.org / ) est la bibliothèque moqueuse que j'ai le plus utilisée. (Il y en a d'autres: jMock, Mockito, etc.)

La plupart d'entre eux créent un objet à l'exécution, que vous pouvez contrôler. Le flux de base est:

  1. Créer une maquette
  2. Spécifiez comment il doit agir en indiquant au cadre fictif ce à quoi il faut s'attendre. (Cela varie en fonction de la cadre.)
  3. Utilisez la maquette dans votre test comme si c'était la vraie chose
  4. Certains frameworks permettent (ou exiger) que vous "vérifiez" que la maquette a été utilisée correctement.
 0
Author: dplass, 2010-06-07 21:58:43