L'uso di PowerMockito.whenNew () non viene preso in giro e viene chiamato il metodo originale


100

Ho un codice un po 'come questo di seguito:

Class A {
  public boolean myMethod(someargs) {
    MyQueryClass query = new MyQueryClass();
    Long id = query.getNextId();
    // some more code
  }
}
Class MyQueryClass     {
  ....
  public Long getNextId() {
    //lot of DB code, execute some DB query
    return id;
  }
}

Ora sto scrivendo un test per A.myMethod(someargs). Voglio saltare il metodo reale query.getNextId()e restituire invece un valore stub. Fondamentalmente, voglio prendere in giro MyQueryClass.

Quindi nel mio caso di test, ho usato:

MyQueryClass query = PowerMockito.mock(MyQueryClass.class);
PowerMockito.whenNew(MyQueryClass.class).withNoArguments().thenReturn(query);
when(query.getNextId()).thenReturn(1000000L);

boolean b = A.getInstance().myMethod(args);

//asserts

Ho usato @RunWith(PowerMockRunner.class)e @PrepareForTest({MyQueryClass.class})all'inizio della mia lezione di prova.

Ma quando eseguo il debug del test, sta ancora chiamando il vero metodo getNextId()della MyQueryClassclasse.

Cosa mi manca qui? Qualcuno può aiutarmi perché sono nuovo di Mockito e PowerMockito.

Risposte:


220

Hai bisogno di mettere la classe in cui il costruttore viene chiamato nella @PrepareForTestannotazioni invece che la classe che si sta costruendo - vede la costruzione di nuovi oggetti Mock .

Nel tuo caso:

@PrepareForTest(MyQueryClass.class)

@PrepareForTest(A.class)

Più generico:

@PrepareForTest(NewInstanceClass.class)

@PrepareForTest(ClassThatCreatesTheNewInstance.class)


1
Molte grazie. Ora ha funzionato dopo aver incluso la classe corrente, ad esempio A, in @PrepareForTest.
user3942446

2
Trascorro un po 'anche per questo. Grazie @TrueDub. Perché il riferimento è obsoleto. L'ho appena aggiornato. github.com/jayway/powermock/wiki/MockConstructor Dice: Usa l'annotazione @PrepareForTest (ClassThatCreatesTheNewInstance.class) a livello di classe del test case.
Victor Choy,

4
Ho lo stesso problema, ma questa soluzione non funziona per me
dexter

3
Questa soluzione semplicemente non funzionerà se stai usando eclemma per la copertura del codice. L'aggiunta della classe sottoposta a test a @PrepareForTest comporterà una copertura dello 0% per quella classe
ACV

2
La soluzione funzionerà: il test viene eseguito correttamente. Ovviamente l'eclemma non è attrezzato per affrontare PowerMockito. La copertura del codice non fa parte di questa domanda.
TrueDub

3

Come menzionato da @TrueDub nella sua risposta accettata, è necessario aggiungere la classe in cui viene chiamato il costruttore al file @PrepareForTest.

Tuttavia, se si esegue questa operazione, la copertura per quella classe riportata da eclemma e Sonar sarà zero per quella classe

Wiki di Powermockito

Sostituiremo Javassist con ByteBuddy (# 727) e dovrebbe aiutare a risolvere questo vecchio problema. Ma al momento non c'è NESSUN MODO DI USARE PowerMock con la strumentazione JaCoCo On-the-fly. E nessuna soluzione alternativa per ottenere la copertura del codice in IDE.

Quindi la soluzione qui sarebbe rifattorizzare il codice effettivo per utilizzare una factory statica che restituirebbe un'istanza di quella classe e quindi la deriderebbe staticamente.


D'accordo con il tuo commento.
Lathy

Tuttavia, questo non è un problema in Intellij.
ACV

0

Forse puoi semplicemente usare

Mockito.doReturn(value).when(xxx)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.