2010-10-04 1 views
5

Diciamo che sto scrivendo un'applicazione e ho bisogno di essere in grado di fare qualcosa del genere:https finte richiesta in java

String url = "https://someurl/"; 
GetMethod method = new GetMethod(URLEncoder.encode(url)); 
String content = method.getResponseBodyAsString(); 

C'è un modo per fornire un server finta che mi permetteva di gestire il richiesta https? Quello che sto cercando è un modo per scrivere i test unitari, ma ho bisogno di essere in grado di prendere in giro la parte che effettivamente esce a https://someurl in modo da poter ottenere una risposta nota.

+0

Eventuali duplicati di http://stackoverflow.com/q/393099/2093341 – Andrea

risposta

3

Hai essenzialmente due opzioni:

1. astratti la chiamata al quadro e testare questa.

E.g. Riformatta il codice per permetterti di iniettare un'implementazione simulata ad un certo punto. Ci sono molti modi per farlo. per esempio. crea un getUrlAsString() e prendi in giro quello. (anche suggerito sopra). Oppure creare un factory getter url che restituisca un oggetto GetMethod. La fabbrica può essere derisa.

2. Avviare un server di app come parte del test e quindi eseguire il metodo su di esso. (Questo sarà più di un test di integrazione)

Questo può essere ottenuto in diversi modi. Questo può essere esterno al test, ad es. il plugin maven jetty. oppure il test può avviare il server a livello di programmazione. vedere: http://docs.codehaus.org/display/JETTY/Embedding+Jetty

L'esecuzione su https lo complicherà ma sarà ancora possibile con certificati autofirmati. Ma mi chiedo: cosa vuoi testare esattamente? Dubito che sia effettivamente necessario testare la funzionalità https, è una tecnologia collaudata.

Personalmente opterei per l'opzione 1: si sta tentando di testare la funzionalità di una libreria esterna. Di solito non è necessario. Inoltre è buona pratica estrapolare le dipendenze dalle librerie esterne.

Spero che questo aiuti.

1

Date un'occhiata a JWebUnit http://jwebunit.sourceforge.net/

Ecco un esempio di un test ... La sua davvero molto intuitivo.

public class ExampleWebTestCase extends WebTestCase { 
    public void setUp() { 
     super.setUp(); 
     setBaseUrl("http://localhost:8080/test"); 
    } 

    public void test1() { 
     beginAt("/home"); 
     clickLink("login"); 
     assertTitleEquals("Login"); 
     setTextField("username", "test"); 
     setTextField("password", "test123"); 
     submit(); 
     assertTitleEquals("Welcome, test!"); 
    } 
} 
+0

sì, io sono familiarità con JWebUnit, ma qui ho bisogno di essere in grado di prendere in giro l'URL effettivo di essere servito su. JWebUnit funziona quando il sito web/servizio che stai chiamando è effettivamente in esecuzione. – dcp

1

Si può sempre lanciare un server thttpd come parte della vostra unit test per servire le richieste a livello locale. Anche se, idealmente, hai un ben testato GetMethod, e poi puoi semplicemente deriderlo, e non avere in realtà un server remoto in giro per TUTTI i tuoi test.

Risorse

1

Puoi avvolgere quel codice in qualche classe e hanno WebClient.getUrl() e poi prendere in giro (per esempio jmock) che il metodo per tornare file memorizzati - dire

expectation { 
    oneOf("https://someurl/"), will(returnValue(someHTML)); 
} 
2

Se si sta scrivendo un test di unità, voi non w e qualsiasi dipendenza esterna. dal api,

GetMethod 

estende

HttpMethod 

modo da poter facilmente deridere con la libreria beffardo preferito. La chiamata

method.getResponseBodyAsString() 

si può beffare di restituire tutti i dati che si desidera.

+0

Ma il GetMethod viene creato nel codice stesso, non nel mio test di unità, quindi non posso deriderlo. – dcp

+0

Non capisco, non controlli il codice che stai testando? – hvgotcodes

+0

Controllo il codice, ma l'oggetto GetMethod viene creato all'interno del metodo che sto testando, quindi non posso passare in un oggetto fittizio. Il modo in cui un mock funziona è che lo si imposta in anticipo e lo si passa a qualunque metodo si stia testando, ma in questo caso, l'oggetto GetMethod viene creato all'interno del metodo stesso, quindi non posso passarlo. Se è non chiaro, per favore fatemelo sapere. – dcp

1

fino a che punto ti interessano beffardo questo "Get" chiamata, perché se siete alla ricerca di un generale framework di simulazione fittizia per Java che si integra bene con JUnit e consente di impostare le aspettative che vengono automaticamente asserite quando incorporate in una suite JUnit, quindi è necessario dare un'occhiata a jMock.

Ora, senza più codice, è difficile stabilire se questo è in realtà ciò che si sta cercando, ma una (un po 'inutile) esempio, di qualcosa di simile al codice di esempio che hai scritto, sarebbe andato qualcosa di simile:

class GetMethodTest { 
@Rule public JUnitRuleMockery context = new JunitRuleMockery(); 

@Test 
public void testGetMethod() throws Exception { 
    // Setup mocked object with expectations 
    final GetMethod method = context.mock(GetMethod.class); 
    context.checking(new Expectations() {{ 
     oneOf (method).getResponseBodyAsString(); 
     will(returnValue("Response text goes here")); 
    }}); 

    // Now do the checking against mocked object 
    String content = method.getResponseBodyAsString(); 
} 
} 
+0

Non funzionerà davvero nel mio caso, vedere i miei commenti su hvgotcodes. – dcp

+0

Hmm quindi potrei considerare l'utilizzo di un framework di estensione Java come Object Teams, che è in grado di reindirizzare le chiamate di metodo specifiche ai propri metodi definiti, quindi è possibile sfruttare il punto preciso del flusso di controllo che è necessario modificare, per iniettare o il tuo codice personale o il tuo oggetto deriso. Non importa che si tratti di un metodo pubblico o privato, ObjecTeams funge da superset per Java, quindi puoi fare cose che Java normalmente non sarebbe in grado di fare. – micdah

4

Dai un'occhiata a jadler (http://jadler.net), una libreria di stub/soppressione http su cui ho lavorato per un po 'di tempo. La versione stabile 1.0.0 è stato appena rilasciato, dovrebbe fornire le funzionalità richiesti:

@Test 
public void getAccount() { 

    onRequest() 
     .havingMethodEqualTo("GET") 
     .havingURIEqualTo("/accounts/1") 
     .havingBody(isEmptyOrNullString()) 
     .havingHeaderEqualTo("Accept", "application/json") 
    .respond() 
     .withTimeout(2, SECONDS) 
     .withStatus(200) 
     .withBody("{\"account\":{\"id\" : 1}}") 
     .withEncoding(Charset.forName("UTF-8")) 
     .withContentType("application/json; charset=UTF-8"); 

    final AccountService service = new AccountServiceRestImpl("http", "localhost", port()); 
    final Account account = service.getAccount(1); 

    assertThat(account, is(notNullValue())); 
    assertThat(account.getId(), is(1)); 
} 


@Test 
public void deleteAccount() { 

    onRequest() 
     .havingMethodEqualTo("DELETE") 
     .havingPathEqualTo("/accounts/1") 
    .respond() 
     .withStatus(204); 

    final AccountService service = new AccountServiceRestImpl("http", "localhost", port()); 
    service.deleteAccount(1); 

    verifyThatRequest() 
     .havingMethodEqualTo("DELETE") 
     .havingPathEqualTo("/accounts/1") 
    .receivedOnce(); 
}