2010-10-04 17 views
5

Powiedzmy Piszę aplikację i muszę być w stanie zrobić coś takiego:mock https zażądać w java

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

Czy istnieje sposób, aby dostarczyć makiety serwer, który pozwoliłby mi obsłużyć Żądanie https? To, czego szukam, jest sposobem na napisanie testów jednostkowych, ale muszę być w stanie wyśmiać część, która faktycznie wychodzi na zewnątrz, aby uzyskać znaną odpowiedź.

+0

Możliwy duplikat http://stackoverflow.com/q/393099/2093341 – Andrea

Odpowiedz

3

można zasadniczo są dwie opcje:

1. Streszczenie wezwanie do ram i przetestować.

Np. zmień kod, aby umożliwić wstrzyknięcie fałszywej implementacji w pewnym momencie. Istnieje wiele sposobów, aby to zrobić. na przykład utwórz getUrlAsString() i udawaj, że to. (również sugerowane powyżej). Lub utwórz fabrykę pobierającą URL, która zwraca obiekt GetMethod. Wtedy fabryka może zostać wyśmiana.

2. Uruchom serwer aplikacji w ramach testu, a następnie uruchom dla niego metodę. (Będzie to bardziej test integracji).

Można to osiągnąć na kilka sposobów. Może to być na zewnątrz test, np. wtyczka maven. lub test może programowo uruchomić serwer. zobacz: http://docs.codehaus.org/display/JETTY/Embedding+Jetty

Uruchomienie tego za pomocą protokołu HTTPS utrudni to, ale nadal będzie możliwe z samopodpisanymi certyfikatami. Ale zadałbym sobie pytanie - co dokładnie chcesz przetestować? Wątpię, czy musisz przetestować funkcjonalność https, sprawdzoną technologię.

Osobiście wybrałbym opcję 1 - próbujesz przetestować funkcjonalność zewnętrznej biblioteki. Zazwyczaj jest to niepotrzebne. Dobrym zwyczajem jest także streszczać swoje zależności w zewnętrznych bibliotekach.

Mam nadzieję, że to pomoże.

1

Spójrz na JWebUnit http://jwebunit.sourceforge.net/

Oto przykład testu ... Jej naprawdę bardzo intuicyjny.

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

tak, jestem zaznajomiony z JWebUnit, ale tutaj muszę być w stanie mock rzeczywisty adres doręczenia w górę. JWebUnit działa, gdy strona/usługa, do której dzwonisz, faktycznie działa. – dcp

1

Zawsze możesz uruchomić serwer thttpd jako część testów jednostkowych służyć żądań lokalnie. Jednak najlepiej, jeśli masz dobrze przetestowany GetMethod, a następnie możesz po prostu z niego kpić i nie musisz mieć zdalnego serwera dla WSZYSTKICH twoich testów.

Resources

1

Można owinąć ten kod w jakiejś klasie i mają WebClient.getUrl() a potem kpić (np jmock) metoda, aby powrócić zapisane pliki - powiedz:

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

Jeśli piszesz test jednostki, nie musisz i wszelkie zewnętrzne zależności. z API

GetMethod 

rozciąga

HttpMethod 

dzięki czemu można łatwo drwić go ze swoim ulubionym biblioteki drwiącym. Twoje połączenie może zostać wyśmiany, aby zwrócić wszystkie żądane dane.

+0

Ale GetMethod jest tworzony w samym kodzie, a nie w jednostce testowej, więc nie mogę tego wyśmiać. – dcp

+0

Nie rozumiem, nie kontrolujesz testowanego kodu? – hvgotcodes

+0

Kontroluję kod, ale obiekt GetMethod jest tworzony w metodzie testowanej przeze mnie, więc nie mogę przekazać fałszywego obiektu. Sposób, w jaki działa makieta, polega na tym, że wcześniej skonfigurowałeś go i przekazałeś do jakiejkolwiek testowanej metody, ale w tym przypadku obiekt GetMethod jest tworzony w samej metodzie, więc nie mogę go przekazać. Jeśli to jest nie jasne, proszę dać mi znać. – dcp

1

Do jakiego stopnia jesteś zainteresowany szyderczy to „Get” połączenia, ponieważ jeśli szukasz ogólna celowa szydercza struktura dla Javy, która dobrze integruje się z JUnitem i pozwala na ustawienie oczekiwań, które są automatycznie potwierdzane po włączeniu do pakietu JUnit, wtedy naprawdę powinieneś spojrzeć na jMock.

Teraz bez więcej kodu, trudno określić, czy jest to rzeczywiście to, czego szukasz, ale (nieco bezużyteczny) przykład, coś podobnego do kodu np napisałeś, pójdzie coś takiego:

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

Naprawdę nie zadziała w moim przypadku, zobacz moje komentarze do hvgotcodes. – dcp

+0

Hmm, wtedy mógłbym rozważyć użycie architektury Java, takiej jak Object Teams, która może przekierowywać określone wywołania metod do własnych zdefiniowanych metod, dzięki czemu możesz dotrzeć do dokładnego punktu przepływu sterowania, który musisz zmienić, aby wstrzyknąć albo twój własny kod, albo twój wyśmiewany obiekt. Nie ma znaczenia, czy jest to metoda publiczna czy prywatna, ObjecTeams działa jako nadzbiór do Javy, więc możesz robić rzeczy, których normalnie Java nie byłaby w stanie zrobić. – micdah

4

Spójrz na jadler (http://jadler.net), http stub stub/drwiąc bibliotekę, nad którą pracowałem od jakiegoś czasu. 1.0.0 stabilna wersja została właśnie wydana, powinien zapewnić możliwości, możesz wnioskować:

@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(); 
}