2014-12-31 17 views
5

Sto cercando di sostituire JMock con Mockito (1.10.17). Ho già fatto alcuni test di unità con successo, ma ora voglio utilizzare la funzione di timeoutjava.lang.VerifyError con Mockito 1.10.17

verify(publisher, timeout(5000)).notifySubscribers(any(BecameMasterMessage.class)); 

e ottengo questa eccezione:

java.lang.VerifyError: (class: org/mockito/internal/verification/VerificationOverTimeImpl, method: verify signature: (Lorg/mockito/internal/verification/api/VerificationData;)V) Incompatible argument to function 
    at org.mockito.verification.Timeout.<init>(Timeout.java:32) 
    at org.mockito.verification.Timeout.<init>(Timeout.java:25) 
    at org.mockito.Mockito.timeout(Mockito.java:2164) 

Il problema si verifica in IntelliJ e con Maven. C'è solo una versione di Mockito sul classpath. C'è anche JMock 2.5.1 sul classpath che non posso rimuovere dal momento che il 99% dei miei test di unità usano ancora JMock in questo momento. Non so se questo ha qualcosa a che fare con questo.

AGGIORNAMENTO: Ho provato con JMock 2.6.0 e Hamcrest 1.3 ma il risultato è lo stesso.

UPDATE 2:

Questo funziona:

Thread.sleep(5000); 
verify(m_publisher).notifySubscribers(any(BecameMasterMessage.class)); 

E questo non lo fa:

verify(publisher, timeout(5000)).notifySubscribers(any(BecameMasterMessage.class)); 

UPDATE 3: ho fatto un piccolo progetto di prova che ha lo stesso identico problema : Vedi https://github.com/wimdeblauwe/mockito-verify-problem ed eseguilo da IntelliJ o con Maven.

+0

Questa è una stupida domanda "spegni e riaccendi", ma ti viene chiesto: hai ripulito gli artefatti della compilation? Anche se esiste una sola versione di Mockito sul classpath, VerificationOverTimeImpl viene ribattezzato di recente da VerificationWithTimeoutImpl 1.9.5 e se hai mai usato 1.9.5 o precedente, un file di una classe persistente potrebbe buttare via tutto. –

+0

@JeffBowman Ho fatto un 'mvn clean install' per assicurarmi che non fosse questo il problema. Ora ho modificato la domanda con un collegamento a un progetto di esempio che mostra il problema. –

risposta

5

Il problema qui è una sfortunata costellazione tra TestNG, JUnit e Mockto. Per risolvere il problema, è sufficiente aggiungere una dipendenza a JUnit 4.0 o superiore (la versione più recente è attualmente 4.12):

<dependency> 
    <groupId>junit</groupId> 
    <artifactId>junit</artifactId> 
    <version>4.12</version> 
</dependency> 

Ecco i dettagli:

TestNG, che è apparentemente il test framework, dichiara una dipendenza dalla vecchia versione di JUnit 3.8.1. Mockito non dichiara affatto una dipendenza da JUnit ma utilizza alcune classi JUnit introdotte in JUnit 4.0 (!).

Edit:

Il metodo Mockito#timeout() nel tuo esempio crea un'istanza Timeout che a sua volta crea un'istanza di VerificationOverTimeImpl. Il metodo VerificationOverTimeImpl#verify() gestisce un errore di tipo ArgumentsAreDifferent che è una sottoclasse di org.junit.ComparisonFailure.

Da JUnit versione 3.8.1 a 4.x la gerarchia di classi di ComparisonFailure è stata modificata in AssertionError anziché in Error come classe di base. Il VerifiyError è causato dal fatto che lo VerificationOverTimeImpl#handleVerifyException() richiede un AssertionError ma verrà invocato con un Error quando viene utilizzato JUnit 3.8.1.

+0

Grazie, lo aggiusterò così ora. Non sarebbe meglio che per Mockito dichiarare una dipendenza da JUnit? Quindi Maven avrebbe scelto il buon problema con la versione di JUnit. –

+0

'org.mockito.exceptions.verification.junit.ArgumentsAreDifferent' estende' junit.framework.ComparisonFailure', 'VerifyError' è un problema di collegamento. La JVM pensa che junit.framework.ComparisonFailure in JUnit 3.xe JUnit 4.x siano sufficientemente diversi da fallire quando si collega 'org.mockito.exceptions.verification.junit.ArgumentsAreDifferent'. In ogni caso sul fronte del mockito il problema è che questa parte dell'API non dovrebbe fare affidamento su JUnit. – Brice

+0

Questo rivela anche che Mockito non è più compatibile con JUnit 3.x – Brice

0

EDIT: Sembra che Stefan abbia risposto per primo. La sua diagnostica è quasi corretta, tuttavia, org.mockito.exceptions.verification.junit.ArgumentsAreDifferent estende junit.framework.ComparisonFailure, che è presente in JUnit 3.x ed è una dipendenza di TestNG 5.x. Lo stesso VerifyError ha probabilmente qualcosa da fare quando la JVM sta eseguendo il collegamento in quanto vi sono modifiche nel tipo ComparisonFailure tra JUnit 3.xe JUnit 4.x.

In ogni caso il problema in Mockito è che utilizza una classe JUnit dove non dovrebbe.E che Mockito non supporta più JUnit 3.x.

tl; tr

Abbiamo un problema nel codice internamente la modalità di verifica che si sta utilizzando utilizzare una classe JUnit, che non è nel classpath. L'aggiunta di JUnit nella dipendenza del tuo POM risolverà le cose.

Grazie per la segnalazione. Ho creato un problema su GitHub (#152)

lunga storia

Per qualche ragione TestNG 5.xxx rendere la JVM non riuscire con un VerifyError, su un metodo che non è nemmeno chiamato a quel punto.

java.lang.VerifyError: (class: org/mockito/internal/verification/VerificationOverTimeImpl, method: verify signature: 
    (Lorg/mockito/internal/verification/api/VerificationData;)V) Incompatible argument to function 

Ma il passaggio alla versione più recente di TestNG, 6.8.something rendere la JVM non riescono con una causa comprensibile: NoClassDefFoundError

java.lang.NoClassDefFoundError: junit/framework/ComparisonFailure 

che indica il vero problema qui, ora c'è solo per trovare quale la classe dipende da JUnit. Questa classe è ArgumentsAreDifferent che si estende junit.framework.ComparisonFailure, questa eccezione viene visualizzata in un blocco try/catch in VerificationOverTimeImpl necessario per la verifica del timeout.

Questo problema è stato presente probabilmente dal 1.10.x durante la correzione di alcuni problemi di timeout.

Nota Ho copiato questa risposta anche su mailing list.

+0

Hai ragione, 'ArgumentsAreDifferent' si estende da' junit.framework.ComparisonFailure'. Quindi la mia risposta è abbastanza sbagliata a quel punto. Dopo aver esaminato il problema un po 'più avanti, penso che il problema sia la gerarchia di classi di 'ComparisonFailure'. È una sottoclasse di 'AssertionFailedError' che è una sottoclasse di 'Error' in JUnit 3.8.1 ** ma ** una sottoclasse di' AssertionError' in JUnit 4.x. Quando si modifica la versione 3.8.1 di "AssertionFailedError" per essere una sottoclasse di "AssertionError", tutto funziona correttamente. –

+0

@StefanFerstl Buona cattura! È molto probabile che JVM veda questa gerarchia cambiare come errore quando esegue il collegamento. – Brice

Problemi correlati