Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Sunday, 15 January 2012

Scripting Language with Thundax P-Zaggy

In this article I will show you the approach taken to solve a common problem: Creating your own Scripting Language using a compiler. Sometimes we need to create our own language and to achieve that we either can create from scratch a lexical analyser in a high level language or use an open source automatic generator of lexical analysers. As I do not want to spent too much time in this task, I obviously chose the second one using an easy approach using JFLEX and CUP. There are many to choose from, e.g. Antlr, JavaCC, SableCC, Coco/R, BYacc/J, Beaver, etc. but I like the way Cup/Jflex work together. Jflex will automatically generate the finite automata of the lexical analyser through the regular expressions that define the tokens from a language. CUP is a system written in Java used to generate LALR syntax analysers. Cup file will contain the syntax definition of the language (Grammar) using a notation similar to BNF (Backus-Naur).
This approach will allow me to create a small compiler which will contain a lexical analyser, a syntax analyser and a semantic analyser without having to add extra workload to my simple Language builder. Cup/Jflex compiler will handle whether the language is well defined or not and in my Delphi project I only have a dummy function that will run if the previous compiler returns 0 errors.
I have also taken advantage of the SynEdit multi-line edit control to enhance the visualization of the simple Scripting Language. The exposed example is pretty basic and it will help to keep the grammar out of the Delphi code. I have tried other Delphi alternatives like GOLD parser and Coco/R but I did not get the expected results. So, If you have any better idea, please do let me know!.
This example will allow the user to define the graph by calling the layout object and connecting one node from another using a numeric description. In left side figure you can actually see the basics of the language and its definition. It invokes the layout object and then it generates a connection from the node(1) to node(2) and it ends the sentence with ";" character. There is no need to define the nodes as if a node does not exist it will be automatically created. The compiler created will manage all kind of errors and warnings and it will inform the user about them. Check that it will inform whether you are committing a lexical error (non recognized symbols, etc) and syntax error (bad composed expressions) through an Error or a semantic error (duplicated lines) through a warning.
A most developed example is shown in the following figure:
Once the language is free of errors, the generator is enabled and P-Zaggy can build the graph using the instructions previously defined and analysed by the external compiler. Note that to be able to check the language you must have installed Java.

The following graph have been created using the basic language:
As you can see it is faster than placing all the objects with the mouse and we can use external tools to generate the script and then check them with the compiler.

Here you can get the latest version of the app:


Jflex regular expressions:

<YYINITIAL>layout {
  if (CUP$parser$actions.verbose)
    System.out.println(yytext());
  pos += yytext().length();
  return new Symbol(sym.layout, new sToken(pos - yytext().length(), yyline, yytext()));
}
<YYINITIAL>node  {
  if (CUP$parser$actions.verbose)
    System.out.println(yytext());
  pos += yytext().length();
  return new Symbol(sym.node, new sToken(pos - yytext().length(), yyline, yytext()));
}
<YYINITIAL>\( {
  if (CUP$parser$actions.verbose)
    System.out.println(yytext());
  pos += yytext().length();
  return new Symbol(sym.OpenBracket, new sToken(pos - yytext().length(), yyline, yytext()));
}
<YYINITIAL>\)  {
  if (CUP$parser$actions.verbose)
    System.out.println(yytext());
  pos += yytext().length();
  return new Symbol(sym.CloseBracket, new sToken(pos - yytext().length(), yyline, yytext()));
}
<YYINITIAL>tonode {
  if (CUP$parser$actions.verbose)
    System.out.println(yytext());
  pos += yytext().length();
  return new Symbol(sym.tonode, new sToken(pos - yytext().length(), yyline, yytext()));
}
<YYINITIAL>parameters  {
  if (CUP$parser$actions.verbose)
    System.out.println(yytext());
  pos += yytext().length();
  return new Symbol(sym.parameters, new sToken(pos - yytext().length(), yyline, yytext()));
}
<YYINITIAL>\. {
  if (CUP$parser$actions.verbose)
    System.out.println(yytext());
  pos += yytext().length();
  return new Symbol(sym.dot, new sToken(pos - yytext().length(), yyline, yytext()));
}
<YYINITIAL>\; {
  if (CUP$parser$actions.verbose)
    System.out.println(yytext());
  pos += yytext().length();
  return new Symbol(sym.endSentence, new sToken(pos - yytext().length(), yyline, yytext()));
}
<YYINITIAL>[0-9]+ {
  if (CUP$parser$actions.verbose)
    System.out.println(yytext());
  pos += yytext().length();
  return new Symbol(sym.INTEGER, new sToken(pos - yytext().length(), yyline, yytext()));
}

[ \t\r\n]+  { pos = 1; }
[a-z]+          {
  System.out.println("ERROR at line "+(Integer.valueOf(yyline)+1) + ": '" +yytext() + "' not recognized");
  pos += yytext().length();
  return new Symbol(sym.ff, new sToken(pos - yytext().length(), yyline, yytext())); }
.   {
  System.out.println("ERROR at line "+(Integer.valueOf(yyline)+1) + ": '" +yytext() + "' not recognized");
  pos += yytext().length();
  return new Symbol(sym.ff, new sToken(pos - yytext().length(), yyline, yytext()));
}

Cup grammar:

terminal        sToken  layout, node, OpenBracket, CloseBracket, tonode, parameters, dot, endSentence, ff;

terminal  sToken          INTEGER, ITEM, QUOTE;

non terminal  scriptClass graphLine;
non terminal    sToken          itemBracket, itemReturned;

graphLine ::=  layout : t1
   dot : t2
   node : t3
   itemBracket : e1
   dot : t6
   tonode : t7
   itemBracket : e2
          endSentence : t10
          graphLine
                        {:
    scriptLines.AddTokens(e1, e2);
    RESULT = scriptLines; :}
          | error;

itemBracket ::= OpenBracket : t4
   itemReturned : e1
   CloseBracket : t5 {: RESULT = (sToken)e1; :}
                        | error;

itemReturned ::= INTEGER : e1 {: RESULT = (sToken)e1; :}
                 | error;

Related links:

Wednesday, 31 March 2010

Protocol Buffer

This article is related to serialization using protobuf a Google's data interchange format. I've been using XML serialization for several years in my Delphi win32 applications, and I was looking for a nicer system. Then I discovered this interesting system that is able to serialize / deserialize objects in a plain format, more human readable instead of the cumbersome XML format. It's a pity that the library isn't implemented on Delphi, but at least there are a lot of programming languages where the library is now implemented. You can find a list here. For testing the power of the library I decided to give it a go in a Java project. This will help me to brush up my Java skills and go further with a protobuf implementation. But one of the primary points behind Google Protocol Buffers is to have a more efficient data packet. Their particular approach uses a stream of binary data rather than the text based on XML. This makes for much less data being sent around and for a much faster parsing. My example will show you the general idea, the easy to build and use, the quick parse and the simplicity of the project.
To some extend I think that the idea is very good, but I'll wait changing my XML serialization until there is a Delphi release of the Protocol Buffer (I'm crossing my fingers). Anyway here you can see a simple example defining the ".proto" file, and the generation of the parser class.

Graph.proto:

package Graphs;

option java_package = "example.graph";
option java_outer_classname = "Graph";

message Node {
  required string id = 1;
  required int32 weight = 2;
}

message Edge {
  required string id = 1;
  required int32 weight = 2;
  required Node source = 3;
  required Node target = 4;
}


For generating the parser class, we need to download the last protobuf compiler (for win32):

C:\protoc-2.3.0-win32>protoc Graph.proto --java_out=C:\temp

After that, we'll get the Graph.java class that will help us serializing our objects. I've created a Serializator class that will handle the node class and will serialize it using the protobuf class:

node.java:

package example.graph;

public class node {
 private String id;
 private int weight;
 
 public node(String id, int weight) {
  setId(id);
  setWeight(weight);
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getId() {
  return id;
 }

 public void setWeight(int weight) {
  this.weight = weight;
 }

 public int getWeight() {
  return weight;
 }
 
 public String toString() {
  return "Id: " + id + " Weight: " + String.valueOf(weight);
 }
}

Serializator.java:

package example.graph;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import example.graph.Graph.Node;

public class Serializator {
 public void SerializeNode(node n) throws IOException {
  FileOutputStream output = new FileOutputStream("node" + String.valueOf(n.getId()));
  
  Node.Builder nodeS = Node.newBuilder();
  nodeS.setId(n.getId());
  nodeS.setWeight(n.getWeight());
  nodeS.build().writeTo(output); 
 }
 
 public node DeserializeNode(int nodeId) throws FileNotFoundException, IOException {
  Node nodeD = Node.parseFrom(new FileInputStream("node" + String.valueOf(nodeId)));
  node n = new node(nodeD.getId(), nodeD.getWeight());
  return n;
 }
}

exampleGraphMain.java:

package example.graph;

import java.io.IOException;

public class exampleGraphMain {

 /**
  * @param args
  * @throws IOException 
  */
 public static void main(String[] args) throws IOException {

  //Serialization (Creating Nodes)
  node n = new node("1", 3);
  node n2 = new node("2", 10);
  
  System.out.println(n.toString());
  System.out.println(n2.toString());
  
  Serializator sr = new Serializator();
  sr.SerializeNode(n);
  sr.SerializeNode(n2);
  
  //Deserialization (Reconstructing Nodes)
  node n3 = sr.DeserializeNode(1);
  node n4 = sr.DeserializeNode(2);

  System.out.println(n3.toString());
  System.out.println(n4.toString());  
 }
}


If you see the generated files "node1 and node2" you'll see them in a byte code format.

Enjoy the reading!.

Wednesday, 15 July 2009

Friday, 3 July 2009

Hacer una llamada a un método de una DLL utilizando Jawin

Java no dispone de una librería propia para el acceso a las DLL (Dinamyc Linking Library). Para ello, utilizaremos Jawin, una librería que nos permite poder trabajar con los métodos de una librería. Java dispone del JNI (Java Native Interface), que es un framework que permite a java interactuar con otros programas escritos en otros lenguajes. Podemos utilizar JNI para interaccionar con los métodos de la DLL, pero es bastante complicado de utilizar. En éste artículo, veremos lo sencillo que es utilizar la librería de Jawin. Para mi ejemplo, he creado una pequeña DLL con delphi, donde hay un método que suma dos enteros y devuelve el resultado. Primero, necesitamos descargar la última versión de la librería Jawin. En éste enlace, podemos descargar la última versión: jawin 2.0-alpha1. Una vez descargada, la descomprimimos y la dejamos en la C:\, luego veremos el porqué.

Primero, crearé la DLL de delphi. Aquí os dejo el código fuente:




library Project1;

uses
SysUtils,
Classes;

{$R *.res}

function AddIntegers(_a, _b: integer): integer; stdcall;
begin
Result := _a + _b;
end;

exports
AddIntegers;

begin
end
.




Como podéis comprobar, es realmente sencillo generar una DLL, simplemente hay que marcar que métodos queremos exportar y listo!.

Para poder visualizar los métodos de las DLL, yo utilizo 2 herramientas muy buenas: DLL Export Viewer y Dependency Walker. Las 2 son gratuitas, y permiten visualizar los métodos que tenemos dentro de la DLL.

En el caso de mi dll, aquí os dejo el pantallazo de la visualización con las 2 aplicaciones:

Luego, para la implementación en Java, crearé un proyecto con Eclipse y añadiré allí las librerías necesarias para la aplicación.

El proyecto tiene el siguiente aspecto:

He añadido las librerías jawin.jar y jawin-stubs.jar a mi proyecto. Si vamos a la C:\jawin-2.0-alpha1 encontraremos los ficheros y las librerías necesárias. Además tenemos que tener en cuenta la librería jawin.dll, que luego os diré como hay que utilizarla.

Ahora, el código fuente del ejemplo:




package test;

import org.jawin.COMException;
import org.jawin.FuncPtr;
import org.jawin.ReturnFlags;

public class AddNumbers {
public static void main(String[] args) throws Exception {
FuncPtr addNum = null;

try {
addNum = new FuncPtr("Project1.dll", "AddIntegers");

Integer g = addNum.invoke_I(3, 5, ReturnFlags.CHECK_HRESULT);
System.out.println("Suma = " + g);
} catch (COMException e) {
e.printStackTrace();
throw e;
} finally {
if (addNum != null) {
try {
addNum.close();
} catch (COMException e) {
e.printStackTrace();
throw e;
}
}
}
}
}




Como podéis ver, hago la llamada a mi dll, y espero el resultado de la suma de los valores. Como resultado tendriamos que ver que la aplicación devuelve lo siguiente:

Loading jawin from hardcoded path C:\jawin-2.0-alpha1\bin\jawin.dll
Suma = 8

Antes de ejecutar el programa, tenemos que vincular la dll de jawin con nuestra aplicación, y ésto hay que hacerlo de la siguiente manera:

Cuando hacemos Run Configurations, tenemos que introducir la siguiente línea en los argumentos de la maquina virtual:

-Dorg.jawin.hardlib=C:\jawin-2.0-alpha1\bin\jawin.dll

De esta manera le estamos diciendo a la aplicación dónde tiene la dll del jawin. Como podéis ver, es bastante sencillo de utilizar, y podemos encontrar un montón de ejemplos dentro de la librería. La otra batalla importante que hay con esta librería es con el tema del los Strings, ya que los métodos que tiene, devuelven matrices de bytes, y tenemos que parametrizar la salida mediante la longitud del String. Buscaré un ejemplo un poco interesante y lo publicaré.
Espero que os sirva de ayuda!.
  • Enlaces de interés:
Error con la JNI.

Wednesday, 1 July 2009

Implementación de un driver Modbus

Disponemos de varias librerías open source para la comunicación con el protocolo Modbus. Tanto en Java como en Delphi disponemos de Jamod y de Delphi Modbus Library. La instalación de las 2 és muy simple, la que tiene un poco más de complicación es la de Delphi, porqué hay que instalar los packages. Las siguientes imágenes de configuración muestran la instalación de los paquetes en delphi 2009 con Indy 10.

Configuración e instalación del Package:


instalar:


Una vez instalados los componentes, podemos realizar nuestras aplicaciones incrustando un componente cliente o servidor de Modbus. Para hacer las pruebas necesitamos un equipo que trabaje con Modus, por ejemplo un PLC. Algún día de estos os mostraré como realizar la configuración del driver y como realizar la conexión con algún dispositivo conocido.

Con el jamod, la cosa también es bastante simple, solo hay que descargarse la última versión de la aplicación: Jamod Modbus Library. Luego en la misma web nos muestran como realizar una aplicación cliente y servidora utilizando su librería. Aquí os dejo los enlaces, para la configuración del driver mediante TCP:

Master:
http://jamod.sourceforge.net/development/tcp_master_howto.html

Slave:
http://jamod.sourceforge.net/development/tcp_slave_howto.html

Tuesday, 30 June 2009

Concordion

Bueno, este mes ya veo que me estoy superando con la friolera de más de 30 artículos. Espero que os de tiempo de leerlos todos porque ya veis que son muy interesantes. En éste artículo y continuando con mi planificación voy a hablaros de Concordion. Hace unas horas os estuve entreteniendo con FIT (Framework for Integrated Test), pues bién, Concordion es una mejora de éste marco de trabajo y mucho más intuitivo para los lenguages Java, .NET y Ruby. Concordion ha sido desarrollado por David Peterson, y uno de sus desarrolladores es José Manuel Beas, el cual podéis encontrar en mi lista de blog roll. Éste al igual que FIT trabaja mediante tablas HTML, pero es mucho más fácil de añadirlo a nuestro proyecto Java. Mediante una keywords muy básicas, podemos crear nuestras hojas de test para comprobar que el programa devuelve lo que nosotros queremos.
  • Que necesitamos para empezar?
Primero, descargamos la última versión de concordion desde la misma web: Concordion-1.3.1. Luego una vez descargado, tenemos que añadir las librerias necesárias a nuestro class path en el eclipse:

Como podéis observar, tengo enlazadas las librerías concordion-1.3.1.jar, la última versión de la junit (junit-4.6.jar) y las ognl-2.6.9.jar y xom-1.1.jar. Una vez tengo esto, creo un pequeño package llamado example donde pondré el código que voy a probar.
Podréis encontrar más información del funcionamiento de Concordion en la web : http://www.concordion.org/Tutorial.html.

Ahora, aprovechando el código fuente de mi anterior post (Arithmetic.java) crearé un HTML de pruebas para ver si la clase me genera bien los resultados esperados. Aquí os pongo la definición del fichero java:

ArithmeticTest.java:




/**
* @Author : Jordi Coll
* Test With Concordion
*/
package example;

import org.concordion.integration.junit3.ConcordionTestCase;

public class ArithmeticTest extends ConcordionTestCase {
private int x;
private int y;

public int plus () {
return getX() + getY();
}

public int minus() {
return getX() - getY();
}

public int multiply () {
return getX() * getY();
}

public int divide () {
return getX() / getY();
}

public float floating () {
return (float)getX() / (float)getY();
}

public float sin () {
return (float)Math.sin(Math.toRadians(getX()));
}

public float cos () {
return (float) Math.cos(Math.toRadians(getX()));
}

public void setX(int x) {
this.x = x;
}

public int getX() {
return x;
}

public void setY(int y) {
this.y = y;
}

public int getY() {
return y;
}
}





Como podéis ver, hay que heredar de la clase ConcordionTestCase para que parsee el documento HTML y localice las entradas que queremos.

Una vez ejecutamos el proyecto con el jUnit, nos tiene que aparecerer en la ventana resultado:

C:\Temp\concordion\example\Arithmetic.html Successes: 4, Failures: 2, Exceptions: 1

La parte del HTML es muy fácil. Simplemente tenemos que generar éste con una sería de metaKeywords definidos por concordion. De ésta manera, podemos escribir sobre un método y leer de él con mucha facilidad. Por ejemplo voy a cargar los valores x y y con números y luego voy a comprobar el resultado. Si el resultado es correcto, me marcará el número en verde y sino en rojo.

Arithmetic.html:

El HTML se tiene que decir igual que la clase, pero sin el Test, de esta manera el hace el matching de una clase a su HTML correspondiente.




<html xmlns:concordion="http://www.concordion.org/2007/concordion">
<body>
<p>
x:
<span concordion:execute="setX(#TEXT)">2</span>
y:
<span concordion:execute="setY(#TEXT)">2</span>
- x+y:
<span concordion:assertEquals="plus()">4</span>
</p>
<p>
x:
<span concordion:execute="setX(#TEXT)">2</span>
y:
<span concordion:execute="setY(#TEXT)">2</span>
- x*y:
<span concordion:assertEquals="multiply()">4</span>
</p>
<p>
x:
<span concordion:execute="setX(#TEXT)">2</span>
y:
<span concordion:execute="setY(#TEXT)">2</span>
- x div y:
<span concordion:assertEquals="divide()">1</span>
</p>
<p>
x:
<span concordion:execute="setX(#TEXT)">2</span>
y:
<span concordion:execute="setY(#TEXT)">2</span>
- x / y:
<span concordion:assertEquals="floating()">1.0</span>
</p>
<p>
x:
<span concordion:execute="setX(#TEXT)">2</span>
- sin(x):
<span concordion:assertEquals="sin()">0.034899495</span>
</p>
<p>
x:
<span concordion:execute="setX(#TEXT)">2</span>
- cos(x):
<span concordion:assertEquals="cos()">0.99939084</span>
</p>
</body>
</
html>




En el caso de que la prueba tubiese éxito aparecería:


Si uno de los valores no devolviese el valor esperado, nos aparecería de la siguiente manera:

Una de las cosas más interesantes que he visto y que más me ha gustado ha sido el mostrado de los errores. Si nos equivocamos al escribir un método en el HTML, luego en el resultado nos aparece:



FIT (Framework for integrated test)

FIT, o Framework for Integrated Test, es un marco de trabajo para el aprovechamiento integral de los ensayos o pruebas. Es una herramienta open source para la automatización de pruebas del cliente. Integra el trabajo de los clientes, analistas, testers y desarrolladores. FIT mejora la comunicación y la colaboración. Crea un circuito de retroalimentación entre los clientes y programadores y permite a los clientes y los testers utilizar herramientas como Microsoft Office para dar ejemplos de cómo debe comportarse un programa (sin ser programadores). Con ésta utilidad construimos un simple y poderoso puente entre la empresa y el mundo de la ingeniería del software. Mediante FIT, los clientes pueden proporcionar una mayor orientación en el proceso de desarrollo, y obtienen mayor visibilidad sobre lo que está sucediendo en el producto y si están dentro de los límites o no.

  • Cómo funciona?
Los clientes proporcionan ejemplos de cómo el software debería funcionar. Estos ejemplos serán la pasarela entre los programadores y los testers. Mediante tablas en HTML (ya sea utilizando Microsoft Word o Excel y luego guardando el resultado en HTML) FIT comprueba el valor a obtener por el programa y lo compara con el valor de muestra. En el caso de que pase la prueba marca la casilla en verde y sino en rojo. También puede marcarlo en amarillo para indicar otros estados.

FIT fue inventado por Ward Cunningham en el año 2002. Él creó la primera versión de FIT para java y en junio de 2005 se actualizó la versión para Java, C#, Python, Perl, PHP y SmallTalk. Si miramos en la web de FIT, podemos encontrar versiones para Ruby y Delphi (fit4Delphi).
Han aparecido nuevas herramientas como FitNesse o Concordion de los que hablaré más adelante.

Si nos bajamos la última versión para Java (fit-java1.1) encontraremos varios ejemplos y el código fuente de su utilización, podemos iniciar el programa de prueba ejecutando la siguiente línea en el cmd:

java -classpath fit.jar fit.FileRunner examples/input/arithmetic.html results.html

El ejemplo se basa en parametrizar unos valores de prueba para unas operaciones matemáticas y el resultado esperado. Luego mediante FIT se compara que el resultado esperado por el cliente es el resultado mostrado por el programa:

Plantilla:

Se le indica la clase, las operaciones en las columnas y el resultado esperado. Luego una vez ejecutadas las pruebas podemos ver el resultado:



Mock Objects

Continuando en la misma línea del Test Driven Development, existe una evolución o mejora de los xUnit basada en los Mock Objects. Los Mock Objects utilizan una técnica para que el diseño del software se haga sobre el TDD. Al igual que los xUnit, podemos encontrar ésta técnica en varios lenguajes de programación: java (jMock y EasyMock), Delphi (pascalMock), .NET (NMock), etc. Aquí os mostraré un par de ejemplos sobre la implementación en Java y Delphi.
  • Utilizando jMock:
Para este ejemplo, nos descargaremos el jMock de la web en éste caso la versión 2.5.1 (jmock-2.5.1), y la última versión del jUnit (la 4.6) -> jUnit-4.6.jar. Una vez tenemos todos los .jar descargados, tenemos que añadirlos en el class path de nuestro proyecto. Por lo tanto tenemos que vincularlo de la siguiente manera:

Voy a aprovechar el ejemplo que posteé ayer sobre la clase TArithmetic, y la he implementado en java para simular el mismo comportamiento. Además es muy fácil de seguir sin complicar mucho el código.

De acuerdo con el TDD, primero tenemos que crear el test case:




/**
* @Author : Jordi Coll
* Test With Mock Objects
*/
import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class TestJMockIniCase {
@Test
public void testSayGreeting(){
Arithmetic a = new Arithmetic();
assertEquals(0, a.plus());
}
}





En este caso, como no hemos creado la clase Arithmetic da un error. Para hacer que compile, necesito crear la clase. Luego tenemos que crear una clase llamada ComponentArithmetic que es la que comunicará con la clase Arithmetic para entregarle las variables x y y para sus cálculos. Luego explicaremos el porqué de esto.

Aquí está la clase Arithmetic:




/**
* @Author : Jordi Coll
* Test With Mock Objects
*/
public class Arithmetic {
private ComponentArithmetic component;

public void SetComponent(ComponentArithmetic component) {
this.component = component;
}

public int plus () {
return component.getX() + component.getY();
}

public int minus() {
return component.getX() - component.getY();
}

public int multiply () {
return component.getX() * component.getY();
}

public int divide () {
return component.getX() / component.getY();
}

public float floating () {
return (float)component.getX() / (float)component.getY();
}

public float sin () {
return (float)Math.sin(Math.toRadians(component.getX()));
}

public float cos () {
return (float) Math.cos(Math.toRadians(component.getX()));
}
}




Para seguir con la compilación, tenemos que crear la clase ComponentArithmetic. Como queremos utilizar mock objects, debemos crear ésta como una interfaz:




/**
* @Author : Jordi Coll
* Test With Mock Objects
*/
public interface ComponentArithmetic {
public int getX();
public int getY();
}




Uno de los pre-requisitos para el uso de los mock objects, es que la clase que parametrizaremos la tenemos que declarar como una interfaz. Además, tenemos que utilizar métodos setter para inyectar la instancia de ComponentArithmetic a Arithmetic. (No podemos utilizar la notación "new" en una interfaz).

Ahora, solo tenemos que modificar la clase de test para que cumpla con nuestras expectativas:




/**
* @Author : Jordi Coll
* Test With Mock Objects
*/

import org.jmock.Expectations;
import org.jmock.Mockery;

import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(JMock.class)
public class TestUsingjMock {
//Creamos el contexto para el mock Object
Mockery context = new JUnit4Mockery();

@Test
public void testArithmetic() {
//Mock sobre la clase ComponentArithmetic utilizando la tecnologia de refexión
//La tenemos que definir como variable final
//ya que va a ser utilizada como clase interna
final ComponentArithmetic ca = context.mock(ComponentArithmetic.class);
Arithmetic a = new Arithmetic();
a.SetComponent(ca);

//Ponemos lo que vamos a esperar del mock Object
context.checking(new Expectations() {
{
one(ca).getX();
will(returnValue(2));
one(ca).getY();
will(returnValue(2));
}
});

int plus = a.plus();
//comparamos el resultado con el valor esperado
assertEquals(3, plus);
}
}




(Todo el tema de los expectators lo podemos encontrar en la web del jUnit : http://www.jmock.org/cookbook.html)

Ahora, si ejecutamos el test con el JUnit, obtendremos:

Prueba correcta:

Prueba con error:
  • Utilizando Pascal Mock:
Podemos encontrar la última versión de Pascal Mock en SourceForge. La última versión estable es la 1.1, y podemos descargarla directamente desde aquí. Su utilización es muy parecida al DUnit y hay que generar las interfases necesarias para que los mock object actúen. Podremos encontrar muchos ejemplos dentro del código. El ejemplo que hay dentro del proyecto, lo podemos ejecutar y visualizar:

Es un proyecto que no está muy vivo (desde el 2007 sin ninguna actualización) y es bastante más complicado de utilizar que con java.