2012-04-19 15 views
9

ho semplice caso di test:Mockito - classi beffardi con metodi nativi

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

Dove TableElement è di classe GWT con metodo insertRow definito come:

public final native TableRowElement insertRow(int index); 

Quando lancio di prova sto ottenendo:

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) 

Quali come credo è in relazione con il metodo insertRow essendo nativo. C'è qualche modo o soluzione per deridere tali metodi con Mockito?

risposta

11

Mockito non sembra in grado di simulare i metodi nativi in ​​base a questo Google Group thread. Tuttavia si ha due opzioni:

  1. avvolgere la classe TableElement in un'interfaccia e modelli che si interfacciano per testare correttamente che il SUT chiama il avvolto insertRow(...) metodo. Lo svantaggio è l'interfaccia aggiuntiva che devi aggiungere (quando il progetto GWT dovrebbe averlo fatto nella propria API) e il sovraccarico per usarlo. Il codice per l'interfaccia e l'attuazione concreta sarebbe simile a questa:

    // 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. Usa Powermock ed è Mockito API extension chiamati PowerMockito per deridere il metodo nativo. Lo svantaggio è che si ha un'altra dipendenza da caricare nel progetto di test (sono consapevole che questo potrebbe essere un problema con alcune organizzazioni in cui una libreria di terze parti deve essere verificata per prima per poter essere utilizzata).

Personalmente mi piacerebbe andare con l'opzione 2, come progetto GWT non è in grado di avvolgere le proprie lezioni di interfacce (ed è più probabile che essi hanno metodi più nativi che deve essere preso in giro) e farlo per te solo per avvolgere una chiamata al metodo nativo è solo uno spreco di tempo.

+0

purtroppo non ho alcun controllo sulla classe 'TableElement' - appartiene alla libreria esterna. Tuttavia l'estensione dell'API Powermock Mockito sembra molto interessante, lo controllerò. –

+0

Quando avvolgi le cose di qualcun altro, allora ** tu hai il controllo. :-) Questa è la bellezza dei wrapper, [adattatori] (http://en.wikipedia.org/wiki/Adapter_pattern), o [façades] (http://en.wikipedia.org/wiki/Facade_pattern). – Spoike

+0

Grazie mille per la risposta molto buona e dettagliata. Il wrapping funzionerà e potrei utilizzarlo come ultima risorsa, ma per i miei gusti è troppo sporgente e complicato il codice di produzione solo a scopo di test :(. –

0

Nel caso in cui qualcun altro inciampi su questo: Nel frattempo (in May 2013) è stato impostato GwtMockito, che risolve questo problema senza il sovraccarico di PowerMock.

Prova questo

@RunWith(GwtMockitoTestRunner.class) 
public class MyTest { 

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