2013-03-26 15 views
5

All'interno di un metodo, ho rilevato un'eccezione che voglio prendere in giro.Come deridere un'eccezione durante la creazione di un'istanza di una nuova classe utilizzando Mockito

So prendere in giro un oggetto per generare un'eccezione utilizzando mock.doSomething(), ma ho bisogno di generare un'eccezione remota quando una classe crea una nuova istanza di se stessa.

transient Bicycle bike = null; 

public Bicycle getBicycle() { 
    if (bike == null) { 
     try { 
      bike = new Bicycle(this); 
     } catch (RemoteException ex) { 
      System.out.println("No bikes found"); 
     } 
    } 
    return bike; 
} 

Voglio essere in grado di prendere in giro tutto nel blocco try, ma non capisco come si deridere la creazione di una nuova classe, la seguente riga per essere precisi:

bike = new Bicycle(this); 

ho provato molte prove Mockito diversi, come ad esempio:

Bicycle b = mock(Bicycle.class); 
Mockito.doThrow(new RemoteException()).when(b = new Bicycle()); 

Anche se capisco questa volontà e non funziona, voglio fare qualcosa di simile.

Ho letto la documentazione Mockito e non hanno trovato nulla di utile:

http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html

+0

possibile duplicato di [Come forzare Mockito gettare RemoteException nel test JUnit] (http://stackoverflow.com/questions/15582395/how-to-force-mockito-to-throw-remoteexception-in-junit-test) –

+0

@ ChristofferHammarström Questo non è sicuramente un duplicato. Ho scritto alla domanda precedente e sto cercando due risposte diverse da entrambi. –

risposta

3

È possibile utilizzare un'estensione Mockito, PowerMock, in casi come questo. Consente ai costruttori di essere derisi (vedere https://code.google.com/p/powermock/wiki/MockConstructor).

In questo caso, si potrebbe scrivere qualcosa di simile al seguente test:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ClassUnderTest.class, Bicycle.class}) 
public class ConstructorMockingTest 
{ 
    @Test 
    public void getBicycle() 
    { 
     ClassUnderTest tested = new ClassUnderTest(); 
     whenNew(Bicycle.class).withArguments(tested).thenThrow(new RemoteException()); 

     Bicycle bicycle = tested.getBicycle(); 

     assertNull(bicycle); 
    } 
} 

Più esempi possono essere trovati all'indirizzo: https://code.google.com/p/powermock/source/browse/trunk/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/WhenNewTest.java

7

In genere non è costruttori finte. È possibile fare fare con strumenti come PowerMock, ma generalmente suggerirei di no.

Attualmente, il tuo codice non è effettivamente testabile, se vuoi controllare cosa succede quando viene costruito un nuovo Bicycle. La costruzione di una Bicycle è in realtà un'operazione complessa? Forse vuoi un BicycleFactory, che può essere passato nella tua classe come dipendenza, per esempio - quindi potresti prendere in giro BicycleFactory.createBicycle o qualsiasi altra cosa tu chiami.

I costruttori sono come metodi statici: quando li usi, sei strettamente legato al codice specifico che stai chiamando; non esiste un modo pulito per iniettare altri comportamenti senza approcci come quelli di PowerMock.

+0

Io non credo di aver chiarito ma bicicletta è un'istanza di un'altra classe, non quella questo metodo è attualmente in.Il metodo recupera l'istanza, ma se è nullo, voglio crearne uno nuovo. Non sono sicuro che ciò cambierebbe qualcosa o no? –

+0

@JohnVasiliou: No, per niente. Stai ancora chiamando un costruttore - che fondamentalmente non è qualcosa che puoi semplicemente prendere in giro nei test. –

+0

Ci sono molte situazioni del mondo reale in cui l'istanziazione diretta di una dipendenza è la cosa giusta da fare. Per uno di questi esempi, prendere in considerazione una classe di servizi alle imprese che deve inviare una notifica via e-mail; in Java, una nota API per la posta elettronica è [Apache Commons Email] (http://commons.apache.org/proper/commons-email), dove normalmente si istanzia una sottoclasse 'Email' (di solito,' SimpleEmail'), chiama alcuni setter/adder e infine chiama il metodo 'send()'. È semplice, orientato agli oggetti, * e * facile da testare. –

0

Il tuo getBicycle() ora fa almeno due cose. Recupera ("ottiene") un Bicycle e crea uno Bicycle. Idealmente un metodo o una classe dovrebbe fare solo una cosa, e farlo bene.

Mettere la creazione dell'oggetto in un metodo separato createBicycle() o separati BicycleFactory e modelli che.

Problemi correlati