Utilizzo di Mockito.reset

1

Ho appena letto un sacco di argomenti contro l'utilizzo di Mockito.reset e non ho molto senso. Metti diversamente, sono d'accordo in generale, ma c'è sempre un caso che sembra usare reset è utile o addirittura necessario.

Molto semplificata, la mia classe sotto test è una mappa incapsulata come

class Handler {
    private final Map<String, String> map;

    public void handle(RequestResponse rr) {
        if (rr.isPut()) {
            map.put(rr.key(), rr.value());
            rr.response("OK");
        } else {
            rr.response(map.get(rr.key());
        }
    }
}

Per provarlo, faccio finta RequestResponse e faccio qualcosa di simile a

when(rr.isPut()).thenReturn(true);
when(rr.key()).thenReturn("key");
when(rr.value()).thenReturn("value");
handler.handle(rr);
verify(rr).response("OK");

reset(rr);

when(rr.isPut()).thenReturn(false);
when(rr.key()).thenReturn("key");
handler.handle(rr);
verify(rr).response("value");

reset(rr);

when(rr.isPut()).thenReturn(false);
when(rr.key()).thenReturn("anotherKey");
handler.handle(rr);
verify(rr).response(null);

Posso vedere, sto testando tre cose contemporaneamente:

  • risposta corretta dopo "metti"
  • il valore corretto restituito da get con la stessa chiave
  • null restituito da get con un'altra chiave

Posso immaginare i motivi per separare gli ultimi due test. Tuttavia, entrambi hanno bisogno del primo e ho ancora bisogno di un reset in mezzo? Oppure no?

Aggiornamento

Nel frattempo la classe sotto test è diventata un po 'più complicata e la necessità di reset è più grande. È una sorta di macchina a stati e il test assomiglia a

  • ripeti quanto segue su percorsi diversi
    • prova un passaggio illegale e attendi un'eccezione
    • prova un altro passaggio illegale e attendi un'eccezione
    • fai un passaggio legale e verifica l'output

In realtà ho solo bisogno di due metodi, uno che verifica l'eccezione per un passaggio illegale e l'altro che verifica l'output corretto per un passaggio legale. L'esecuzione di un passaggio illegale non deve cambiare lo stato, quindi è sicuro mischiarlo.

Considera questo esempio: se l'unica sequenza di input valida era A, B, C (tre passaggi) e gli output corrispondenti erano a, b, c , allora un test assomiglia a

checkException("B")
checkException("C")

checkOutput("A", "a")
checkException("A")
checkException("C")

checkOutput("B", "b")
checkException("A")
checkException("B")

checkOutput("C", "c")
checkException("A")
checkException("B")
checkException("C")

percorre l'intero percorso e verifica tutto. Ci vorranno molti test "normali" di verifica delle condizioni per ottenere lo stesso risultato, giusto?

    
posta maaartinus 29.08.2014 - 22:02
fonte

1 risposta

1

Il motivo per cui stai utilizzando reset è perché stai elaborando tre diversi RequestResponse s tramite il gestore. Ma reset è in realtà per quando è necessario modificare le risposte che un oggetto sta facendo. Penso che la cosa concettualmente corretta da fare sia creare tre diversi oggetti RequestResponse. In questo modo non è necessario ripristinare nulla.

Ma il tuo test è ancora imbarazzante. Penso che sia imbarazzante perché l'interfaccia è scomoda. RequestResponse completa il ruolo di entrambi i parametri e il valore restituito. Un approccio sarebbe quello di scrivere un adattatore in un approccio più tipico, qualcosa del tipo:

class Handler {
    private final Map<String, String> map;

    public String handle(boolean isPut, String key, String value) {
        if (isPut) {
            map.put(key, value);
            return "OK";
        } else {
            return map.get(key);
        }
    }
}

class HandlerAdapter {
    final Handler handle;

    public HandlerAdapter(Handler handler) {
         this.handler = handler;
    }

    public void handle(RequestResponse rr) {
       rr.response(handler.handle(rr.isPut(), rr.key(), rr.value()));
    }
}

Il test diventa quindi:

assertEquals("OK", handler.handle(true, "key", "value"));
assertEquals("value", handler.handle(false, "key"));
assertEquals(null, handler.handle(false, "anotherkey"));

Probabilmente lo suddividerei in due test, verificando il corretto ritorno e la mancata corrispondenza della chiave nei test separati. Ovviamente vorrete anche testare correttamente per HandlerAdapter, ma questo dovrebbe essere molto semplice dato che trasferisce solo i dati in Handler.

    
risposta data 31.08.2014 - 18:01
fonte

Leggi altre domande sui tag