2012-04-19 18 views
9

Tengo caso de prueba sencilla:Mockito - clases burlones con métodos nativos

@Test 
public void test() throws Exception{ 
     TableElement table = mock(TableElement.class); 
     table.insertRow(0); 
} 

Dónde TableElement es la clase de GWT con el método insertRow define como:

public final native TableRowElement insertRow(int index); 

Cuando inicio la prueba que estoy recibiendo:

java.lang.UnsatisfiedLinkError: com.google.gwt.dom.client.TableElement.insertRow(I)Lcom/google/gwt/dom/client/TableRowElement; 
    at com.google.gwt.dom.client.TableElement.insertRow(Native Method) 

Que, como creo, está relacionado con el método insertRow que es nativo. ¿Hay alguna manera o solución para burlarse de tales métodos con Mockito?

Respuesta

11

Mockito en sí no parece ser capaz de burlarse de los métodos nativos según este Google Group thread. Sin embargo, usted tiene dos opciones:

  1. envolver la clase TableElement en una interfaz y burlas de esa interfaz para probar adecuadamente que su SUT llama a la envuelta insertRow(...) método. El inconveniente es la interfaz adicional que necesita agregar (cuando el proyecto GWT debería haber hecho esto en su propia API) y la sobrecarga para usarla. El código de la interfaz y la aplicación concreta se vería así:

    // the mockable interface 
    public interface ITableElementWrapper { 
        public void insertRow(int index); 
    } 
    
    // the concrete implementation that you'll be using 
    public class TableElementWrapper implements ITableElementWrapper { 
        TableElement wrapped; 
    
        public TableElementWrapper(TableElement te) { 
         this.wrapped = te; 
        } 
    
        public void insertRow(int index) { 
         wrapped.insertRow(index); 
        } 
    } 
    
    // the factory that your SUT should be injected with and be 
    // using to wrap the table element with 
    public interface IGwtWrapperFactory { 
        public ITableElementWrapper wrap(TableElement te); 
    } 
    
    public class GwtWrapperFactory implements IGwtWrapperFactory { 
        public ITableElementWrapper wrap(TableElement te) { 
         return new TableElementWrapper(te); 
        } 
    } 
    
  2. Uso Powermock y es Mockito API extension llamados PowerMockito burlarse del método nativo. El inconveniente es que tiene otra dependencia para cargar en su proyecto de prueba (soy consciente de que esto puede ser un problema con algunas organizaciones donde una biblioteca de terceros debe ser auditada primero para poder ser utilizada).

Personalmente, me gustaría ir con la opción 2, ya que el proyecto GWT no encapsula sus propias clases en interfaces (y es más probable que tengan más métodos nativos que se deben burlar) y hacerlo por usted mismo solo envolver una llamada a un método nativo es solo una pérdida de tiempo.

+0

Por desgracia, no tienen control sobre la clase 'TableElement' - pertenece a la biblioteca externa. Sin embargo, la extensión de Powermock Mockito API parece muy interesante, la verificaré. –

+0

Cuando envuelve las cosas de otra persona, ** usted ** tiene el control. :-) Esa es la belleza de los envoltorios, [adaptadores] (http://en.wikipedia.org/wiki/Adapter_pattern), o [fachadas] (http://en.wikipedia.org/wiki/Facade_pattern). – Spoike

+0

Muchas gracias por la respuesta muy buena y detallada. El envoltorio funcionará y puedo usarlo como último recurso, pero para mi gusto es demasiado inclinado y complicando el código de producción solo para fines de prueba :(. –

0

En caso de que alguien más se tropiece con esto: Mientras tanto (en May 2013) apareció GwtMockito, lo que soluciona este problema sin la sobrecarga de PowerMock.

Prueba este

@RunWith(GwtMockitoTestRunner.class) 
public class MyTest { 

    @Test 
    public void test() throws Exception{ 
     TableElement table = mock(TableElement.class); 
     table.insertRow(0); 
    } 
} 
Cuestiones relacionadas