2009-03-09 12 views
5

Je suis un gars .NET - et je code principalement en C#. Depuis C# 3.0, nous pouvons utiliser les expressions lambda et les arbres d'expression pour utiliser static reflection. Par exemple, il est possible de mettre en œuvre GetMethodName dans l'extrait suivant pour renvoyer le nom de la méthode passée en paramètre:Comment fonctionne la "réflexion statique" dans Java? (par exemple dans mockito ou easymock)

string methodName = GetMethodName(o => o.DoSomething()); 
Console.WriteLine(methodName); // displays "DoSomething" 

Maintenant, quand je regarde les échantillons Mockito (ou les EasyMock) dans le monde java, je voir:

LinkedList mockedList = mock(LinkedList.class); 
when(mockedList.get(0)).thenReturn("first"); 

Comment ça marche?

Comment fonctionne la méthode when? Comment interprète-t-il mockedList.get(0) comme un appel à la méthode get avec 0 passé comme paramètre et non comme une valeur?

Répondre

5

Les bibliothèques de simulation ne fonctionnent généralement pas avec les arbres d'expression. Ils construisent un type qui implémente l'interface appropriée et répond aux appels de méthode en les enregistrant ou en les validant et en retournant les réponses préprogrammées. Cela est généralement effectué avec un proxy (par exemple, RealProxy dans .NET, Proxy dans Java) ou avec la génération de code dynamique.

Dans le cas d'EasyMock, il utilise Proxy (pour les interfaces, de toute façon), comme vous pouvez le voir dans le code source: regardez org.easymock.internal.JavaProxyFactory.

+0

Proxy sur fonctionne avec des interfaces. De véritables frameworks moqueurs à leur propre génération de code. –

+0

Dans .NET, les frameworks de mocking fortement typés utilisent des arbres d'expression (voir Moq & Rhino) et des proxies dynamiques. Mais ici, je ne comprends toujours pas comment (même avec des proxies) vous pouvez configurer le simulacre en toute sécurité. Que faire si je tape "when (mockedList.get (0) + mockedList.get (2)). ThenReturn (42)"? –

+0

Rhino Mocks existait bien avant les arbres d'expression. Il peut utiliser des arbres d'expression * maintenant * dans certains cas, mais cela ne le fait pas * toujours *. (Cela fonctionne toujours dans .NET 2.0.) Si vous faites un autre appel au faux avant de spécifier le résultat du dernier, les résultats dépendent du mode du faux. –

2

Je n'ai jamais travaillé avec mockito ou easymock mais je ne pense pas que l'appel fasse ce que vous pensez. Il n'interprète pas mockedList.get(0) d'une manière spéciale. La méthode get est exécutée sur l'objet mockedList normalement, et le résultat est remis à when.

1

mockedList.get(0) est la syntaxe pour un appel de méthode, et fait exactement cela. Ce que fait cette méthode n'est pas tout à fait clair. Le type d'exécution de mockedList sera une sous-classe de LinkedList retournée par la méthode mock, qui peut être implémentée à quel point le cadre de simulation est approprié.

4

Java bibliothèques simulacres fonctionnent généralement comme ceci:

Lorsque vous créez une maquette, un proxy réel est créé (que ce soit à partir d'une interface ou une sous-classe), l'instance est en « mode d'enregistrement ». Cela signifie que tout appel ultérieur est enregistré (nom de la méthode, paramètres, retour attendu). Notez que le proxy en mode d'enregistrement ne fait rien d'autre que d'enregistrer les appels. Il n'y a pas de réflexion en soi. Aucune découverte de métadonnées, etc. Bien sûr, ces bibliothèques font quelques astuces (telles que le stockage des invocations dans une variable locale-thread pour gérer les méthodes qui renvoient void) mais l'idée reste la même.

Ensuite, lorsque le "mode replay" est démarré, l'instance simulée vérifie simplement les attentes de la liste des invocations (méthode + paramètres & valeurs de retour).