2009-02-19 19 views
6

Questa potrebbe sembrare una domanda abbastanza dettagliata su Easymock, ma sto incontrando difficoltà nel trovare un sito di supporto/forum/mailing list per questa libreria.Easymock: l'ordine delle catture è importante?

Sto riscontrando un errore durante l'utilizzo del metodo captures() che sembra restituire i parametri catturati in ordine.

Ecco una versione semplificata di quello che sto testando:

public class CaptureTest extends TestCase { 

    // interface we will be mocking 
    interface Processor { 
      void process(String x); 
    } 

    // class that uses the interface above which will receive the mock 
    class Component { 

     private Processor processor; 

     private String[] s = { "one", "two", "three", "four" }; 

     Component(Processor processor) { 
      this.processor = processor; 
     } 

     public void doSomething() { 
      for (int i = 0; i < s.length; i++) { 
       processor.process(s[i]); 
      } 
     } 
} 

    public void testCapture() { 

     //create the mock, wire it up  
     Processor mockProcessor = createMock(Processor.class); 
     Component component = new Component(mockProcessor); 

     //we're going to call the process method four times 
     //with different arguments, and we want to capture 
     //the value passed to the mock so we can assert against it later  
     Capture<String> cap1 = new Capture<String>(); 
     Capture<String> cap2 = new Capture<String>(); 
     Capture<String> cap3 = new Capture<String>(); 
     Capture<String> cap4 = new Capture<String>(); 

     mockProcessor.process(and(isA(String.class), capture(cap1))); 
     mockProcessor.process(and(isA(String.class), capture(cap2))); 
     mockProcessor.process(and(isA(String.class), capture(cap3))); 
     mockProcessor.process(and(isA(String.class), capture(cap4))); 

     replay(mockProcessor); 

     component.doSomething(); 

     //check what values were passed to the mock 
     assertEquals("one", cap1.getValue()); 
     assertEquals("two", cap2.getValue()); 
     assertEquals("three", cap3.getValue()); 
     assertEquals("four", cap4.getValue()); 

     verify(mockProcessor); 
    } 

} 

(Si prega di notare che questo è solo un banco di prova semplificata - So che avrei potuto specificare il valore esatto degli argomenti mi aspetto che passò alla mia mock, ma nel mio caso reale gli argomenti sono oggetti complessi con una manciata di campi, e voglio catturare l'oggetto in modo tale da poter affermare solo alcuni di quei campi senza ricreare l'intero oggetto nel mio caso di test).

Quando eseguo il test, non riesce a:

junit.framework.ComparisonFailure: atteso: < [uno]> ma era: < [quattro]>

che significa che il il parametro che EasyMock sta acquisendo in cap1 non è la prima chiamata al metodo, ma l'ultima (poiché il valore è four). Ottengo gli stessi risultati se inverto le dichiarazioni captures(), cioè utilizzo cap4 con la prima chiamata al metodo, ecc.

Sembra che potrebbe trattarsi di un bug in EasyMock - diversi parametri passati allo stesso metodo in diverse chiamate t sembra essere catturato correttamente.

C'è qualcun altro che utilizza capture() con EasyMock e ha problemi simili? C'è una soluzione facile a tua conoscenza o un modo diverso per catturare i parametri passati ai metodi del mio mock?

Update 1: esempio di codice fisso per mostrare che sto usando createMock, non createStrictMock, ma ottengo lo stesso errore con entrambi (anche se il valore reale di ciò che viene catturato modifiche).

+0

Ho osservato questo problema ed è abbastanza confuso. Se esegui un'istruzione System.out.println su ciascuna delle Capture, vedrai quanto segue con un createMock: four, four, four, four. Con un createStrickMock: due, due, tre, quattro. – hooknc

+0

Quindi sembra proprio un bug! Ho inviato un bug sulla pagina sourceforge di Easymock, speriamo che qualcuno risponda - anche se dalla mancanza di mailing list, forum/commenti sulla home page, ecc., Ho una sensazione che il supporto è estremamente limitato :( –

risposta

4

Ho ricevuto an answer sul bug che ho inviato al sito sourceforge di Easymock e uno sviluppatore ha confermato che si tratta di un bug con questa versione di Easymock.

È davvero un bug. L'acquisizione viene eseguita anche se è già stata eseguita. La soluzione corrente è quello di implementare il proprio oggetto di cattura e sovrascrivere setValue per fare questo:

@Override 
public void setValue(T value) { 
    if(!hasCaptured()) { 
    super.setValue(value); 
    } 
} 
-1

Invece di chiamare EasyMock.createStrictMock (...) basta chiamare EasyMock.createMock (...). Dovresti risolvere i tuoi problemi.

+0

Ho avuto gli stessi problemi con createMock - l'ho modificato per creareStrickMock (e ho dimenticato che era nell'esempio di codice che ho postato) pensando che potrebbe essere d'aiuto con l'ordine delle chiamate al metodo, ma no - lo stesso risultato.Verrà aggiornato l'esempio sopra. –

+0

Hmm, solo come controllo, potresti provare a chiamare checkOrder (falso) dopo aver creato il mock.Potrei mancare qualcosa di ovvio ma sembra un bug.Io sarò in grado di confermarlo sulla mia macchina stasera .. –

+0

stesso risultato con checkOrder (false) –

0

È anche possibile provare a utilizzare EasyMock.createNiceMock (...) anziché EasyMock.createStrictMock (...) o EasyMock.createMock (...).

Anche se, sono d'accordo che sembra più un bug con createMock.

1

Stavo giocando con il tuo test e non ho potuto risolvere. Tuttavia ho esteso la classe Capture per vedere se i valori sono stati impostati in un ordine diverso (ero sospettoso che EasyMock utilizzasse internamente un hash con una chiave generata dai metodi e dai parametri) Ho sbagliato i metodi sono impostati nel corretto ordine. Ma c'è qualcosa di veramente strano in corso .. Sembra che l'algoritmo abbia un qualche tipo di pattern di assegnazione .. Bene, lasciami mostrare il codice e lo strano output .... BTW i cambiamenti da mock, niceMock e strictMock non hanno fatto alcuna deviazione ..

class MyCapture extends Capture<String> { 

    private String id; 

    public MyCapture(String id) { 
     super(); 
     System.out.printf("Constructor %s expecting %s\n", id, this.getClass().getName()); 
     this.id = id; 
    } 

    private static final long serialVersionUID = 1540983654657997692L; 

    @Override 
    public void setValue(String value) { 
     System.out.printf("setting value %s expecting %s \n", value, id); 
     super.setValue(value); 
    } 

    @Override 
    public String getValue() { 
     System.out 
       .printf("getting value %s expecting %s \n", super.getValue(), id); 
     return super.getValue(); 
    } 
} 


public void testCapture() { 

    // create the mock, wire it up 
    Processor mockProcessor = createStrictMock(Processor.class); 
    Component component = new Component(mockProcessor); 

    // we're going to call the process method four times 
    // with different arguments, and we want to capture 
    // the value passed to the mock so we can assert against it later 
    Capture<String> cap1 = new MyCapture("A"); 
    Capture<String> cap2 = new MyCapture("B"); 
    Capture<String> cap3 = new MyCapture("C"); 
    Capture<String> cap4 = new MyCapture("D"); 

    mockProcessor.process(and(isA(String.class), capture(cap1))); 
    mockProcessor.process(and(isA(String.class), capture(cap2))); 
    mockProcessor.process(and(isA(String.class), capture(cap3))); 
    mockProcessor.process(and(isA(String.class), capture(cap4))); 
    replay(mockProcessor); 

    component.doSomething(); 

    // check what values were passed to the mock 
    assertEquals("A", cap1.getValue()); 
    assertEquals("B", cap2.getValue()); 
    assertEquals("C", cap3.getValue()); 
    assertEquals("D", cap4.getValue()); 

    verify(mockProcessor); 
} 

}

* E questa è l'uscita *

Constructor A expecting com.comp.core.dao.impl.CaptureTest$MyCapture 
    Constructor B expecting com.comp.core.dao.impl.CaptureTest$MyCapture 
    Constructor C expecting com.comp.core.dao.impl.CaptureTest$MyCapture 
    Constructor D expecting com.comp.core.dao.impl.CaptureTest$MyCapture 
    calling process A 
    setting value A expecting A 
    calling process B 
    setting value B expecting A <<Setting the wrong guy 
    setting value B expecting A <<Setting the wrong guy 
    setting value B expecting B <<Ops this is the right one..stop 
    calling process C 
    setting value C expecting B <<Setting the wrong guy 
    setting value C expecting B <<Setting the wrong guy 
    setting value C expecting C <<Setting the wrong guy 
    calling process D 
    setting value D expecting C <<Setting the wrong guy 
    setting value D expecting C <<Setting the wrong guy 
    setting value D expecting D <<Ops this is the right one..stop 
    getting value B expecting A 

Spiacente non posso aiutare di più. Potrebbe essere davvero un bug in facile simulazione.

0

Questo è un problema più appropriato per il test basato sullo stato, credo. Con JMockit, si potrebbe risolvere in questo modo:

import mockit.*; 
import static mockit.Mockit.*; 
import mockit.integration.junit3.*; 

public class CaptureTest extends JMockitTestCase 
{ 
    interface Processor { void process(String x); } 

    class Component 
    { 
     private final Processor processor; 
     private final String[] s = {"one", "two", "three", "four"}; 

     Component(Processor processor) { this.processor = processor; } 

     public void doSomething() 
     { 
     for (String value : s) { 
      processor.process(value); 
     } 
     } 
    } 

    @MockClass(realClass = Processor.class) 
    static class MockProcessor 
    { 
     private final String[] expectedValues; 
     private int i; 

     MockProcessor(String... expectedValues) { this.expectedValues = expectedValues; } 

     @Mock 
     void process(String x) 
     { 
     assertEquals(expectedValues[i++], x); 
     } 
    } 

    public void testCapture() 
    { 
     Processor mockProcessor = setUpMock(new MockProcessor("one", "two", "three", "four")); 
     Component component = new Component(mockProcessor); 

     component.doSomething(); 
    } 
} 
0

In breve, ecco cosa ha funzionato per me:

MyClass myMock = EasyMock.createStrictMock(MyClass.class); 

...

EasyMock.checkOrder(myMock, true); // before the capture and verify, not sure if it matters 

...

Capture<MyArg> capturedArgs = new Capture<MyArg>(); 
expect(myMock.search(capture(capturedArgs))).andReturn(someRandomReturn); 

PS: sto usando E asyMock 3.0

Problemi correlati