2010-10-04 6 views
5

Disons que je vous écris une application et je dois être en mesure de faire quelque chose comme ceci:https simulacres demande en java

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

est-il un moyen de fournir un serveur simulé qui me permettrait de gérer les Demande https? Ce que je cherche, c'est un moyen d'écrire des tests unitaires, mais je dois être capable de me moquer de la partie qui sort réellement vers https://someurl pour que je puisse obtenir une réponse connue.

+0

double possible de http://stackoverflow.com/q/393099/2093341 – Andrea

Répondre

3

Vous avez essentiellement deux options:

1. Résumé l'appel au cadre et un test.

E.g. refactoriser le code pour vous permettre d'injecter une fausse implémentation à un moment donné. Il y a plusieurs façons de le faire. par exemple. créer un getUrlAsString() et mock that. (également suggéré ci-dessus). Ou créez une fabrique d'URL getter qui renvoie un objet GetMethod. L'usine peut alors être raillée.

2. Démarrez un serveur d'applications dans le cadre du test, puis exécutez votre méthode par rapport à celui-ci. (Il s'agira plutôt d'un test d'intégration)

Ceci peut être réalisé de plusieurs façons. Cela peut être externe au test, par ex. le plugin maven jetty. ou le test peut démarrer par programme le serveur. voir: http://docs.codehaus.org/display/JETTY/Embedding+Jetty

L'exécution sur https compliquera cela, mais cela sera toujours possible avec des certificats autosignés. Mais je me demandais - que voulez-vous exactement tester? Je doute que vous ayez besoin de tester la fonctionnalité https, c'est une technologie éprouvée.

Personnellement, j'opte pour l'option 1 - vous essayez de tester la fonctionnalité d'une bibliothèque externe. C'est habituellement inutile. En outre, il est recommandé d'extraire vos dépendances aux bibliothèques externes.

Espérons que cela aide.

1

Jetez un oeil à JWebUnit http://jwebunit.sourceforge.net/

Voici un exemple d'un test ... Il est vraiment tout à fait intuitive.

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

oui, je connais JWebUnit, mais ici je dois être en mesure de se moquer de l'URL servis en haut JWebUnit fonctionne lorsque le site Web/service que vous appelez est en cours d'exécution. – dcp

1

Vous pouvez toujours lancer un serveur thttpd dans le cadre de votre test unitaire pour répondre aux demandes locales. Bien que, idéalement, vous ayez bien testé GetMethod, alors vous pouvez juste vous moquer de lui, et ne pas avoir réellement besoin d'un serveur distant pour TOUS vos tests.

Ressources

1

Vous pouvez envelopper ce code dans une classe et ont WebClient.getUrl(), puis se moquer (par exemple jmock) que pour renvoyer les fichiers stockés - dites

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

Si vous écrivez un test unitaire, vous ne ant n'importe quelles dépendances externes. de l'api,

GetMethod 

étend

HttpMethod 

afin que vous puissiez facilement se moquer avec votre bibliothèque préférée moqueur. Votre

method.getResponseBodyAsString() 

l'appel peut être raillé pour retourner les données que vous voulez.

+0

Mais le GetMethod est créé dans le code lui-même, pas dans mon test unitaire, donc je ne peux pas le mocker. – dcp

+0

Je ne comprends pas, vous ne contrôlez pas le code que vous testez? – hvgotcodes

+0

Je contrôle le code, mais l'objet GetMethod est créé à l'intérieur de la méthode que je suis en train de tester, donc je ne peux pas passer dans un objet fantaisie. Le fonctionnement d'un simulacre est que vous le configurez à l'avance et le transmettez à la méthode que vous testez, mais dans ce cas, l'objet GetMethod est créé à l'intérieur de la méthode elle-même, donc je ne peux pas le transmettre. pas clair, s'il vous plaît faites le moi savoir. – dcp

1

Dans quelle mesure êtes-vous intéressé à se moquer de cet appel « Get », parce que si vous êtes à la recherche d'un général but mocking framework pour Java qui s'intègre bien avec JUnit et permet de configurer des attentes qui sont automatiquement affirmées lorsqu'elles sont intégrées dans une suite JUnit, alors vous devriez vraiment jeter un oeil à jMock.

Maintenant, sans plus de code, il est difficile de déterminer si c'est en fait ce que vous cherchez, mais un (peu inutile) par exemple, de quelque chose de similaire à l'exemple de code que vous avez écrit, serait quelque chose comme ceci:

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

Ne fonctionne pas vraiment dans mon cas, voir mes commentaires à hvgotcodes. – dcp

+0

Hmm alors je pourrais envisager d'utiliser un framework d'extension Java comme Object Teams, qui est capable de rediriger des appels de méthode spécifiques à vos propres méthodes définies, ainsi vous pouvez puiser dans le point précis du flux de contrôle que vous devez modifier, injecter soit votre propre code ou votre objet mocké. Peu importe que ce soit une méthode publique ou privée, ObjecTeams agit comme un sur-ensemble à Java, donc vous pouvez faire des choses que Java ne serait normalement pas capable de faire. – micdah

4

Jetez un coup d'œil à jadler (http://jadler.net), une bibliothèque de stubbing/moqueurs http sur laquelle je travaille depuis un certain temps. La 1.0.0 version stable a été vient de sortir, il doit fournir les capacités que vous avez demandé:

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