2017-09-04 6 views
3

Lors de l'écriture d'un test d'intégration pour une application Spring Boot (Service A) qui utilise RestTemplate (et Ribbon under the hood) et Eureka pour résoudre un service B dépendante, je reçois une exception "Aucune instance disponible" lors de l'appel du Service A.Le test d'intégration de démarrage Spring avec WireMock et Eureka échoue avec "Aucune instance disponible"

Je tente de rater le Service B par WireMock, mais je n'arrive même pas au serveur WireMock. Il semble que le RestTemplate tente d'extraire l'instance de Service d'Eureka, qui ne fonctionne pas dans mon test. Il est désactivé via les propriétés.

Service A appelle le service B. La découverte du service est effectuée via RestTemplate, Ribbon et Eureka.

Est-ce que quelqu'un a un exemple de travail qui inclut Spring, Eureka et WireMock?

+0

Si vous êtes d'accord avec le service moqueur B, vous pouvez utiliser 'MockRestServiceServer'. Je peux partager un exemple. – barbakini

+0

Cela pourrait être une option, mais je voudrais inclure l'appel de service réel, même si la réponse est en conserve. – derSteve

+0

Lors de l'utilisation de 'MockRestServiceServer', l'amorçage par ressort fait en réalité l'objet d'un appel. mais seulement cet appel il attrapé par le 'MockRestServiceServer' et il renvoie la réponse que vous avez déterminée. Et pour la partie eureka. C'est déjà un travail de cadre bien cuit et vous n'avez pas besoin de le tester (pour des problèmes de balance de ruban ou de charge, etc.) – barbakini

Répondre

0

C'est ce que je fait dans mon projet:

Quelque part dans la configuration de votre projet:

@LoadBalanced 
@Bean 
public RestTemplate restTemplate(RestTemplateBuilder builder) { 
    RestTemplate restTemplate = builder.build(); 
    restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); 
    return restTemplate; 
} 

@Bean 
public SomeRestClass someRestClass() { 
    SomeRestClass someRestClass = new SomeRestClass (environment.getProperty("someservice.uri"), restTemplate(new RestTemplateBuilder())); 
    return parameterRest; 
} 

Et SomeRestClass:

public class SomeRestClass { 

    private final RestTemplate restTemplate; 

    private final String someServiceUri; 

    public LocationRest(String someServiceUri, RestTemplate restTemplate) { 
     this.someServiceUri= someServiceUri; 
     this.restTemplate = restTemplate; 
    } 

    public String getSomeServiceUri() { 
     return locationUri; 
    } 

    public SomeObject getSomeObjectViaRest() { 
     //making rest service call 
    } 
} 

et la classe de test pour SomeRestClass:

@RunWith(SpringRunner.class) 
@RestClientTest(SomeRestClass.class) 
public class SomeRestClassTest { 
    @Autowired 
    private SomeRestClass someRestClass; 

    @Autowired 
    private MockRestServiceServer server; 

    @Test 
    public void getSomeObjectViaRestTest() throws JsonProcessingException { 
     SomeResponseObject resObject = new SomeResponseObject(); 
     ObjectMapper objectMapper = new ObjectMapper(); 
     String responseString = objectMapper.writeValueAsString(resObject); 

     server.expect(requestTo(locationRest.getSomeServiceUri() + "/some-end-point?someParam=someParam")).andExpect(method(HttpMethod.POST)) 
      .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON_UTF8).body(responseString)); 
     someRestClass.getSomeObjectViaRest(); 

    } 
} 

Note: J'ai dérouté le client eureka car sinon il faut se moquer d'un serveur eureka. J'ai donc ajouté eureka.client.enabled = false dans le test application.properties

+0

Est-ce que le RestTemplate dans ce cas réalise qu'il n'y a pas de ServiceRegistry/Eureka pour demander le point de terminaison de service spécifique?Dans mon test, il ne réalise pas cela et essaie de résoudre un service d'eureka. C'est pourquoi j'ai l'exception. J'ai le paramètre eureka.client.enabled = false défini dans ma configuration -> ce qui signifie qu'il ne s'enregistre pas chez eureka en tant que service lui-même. – derSteve

+0

@derSteve Oui, RestTemplate essaie simplement de frapper l'adresse et MockRestServiceServer attrape cette requête. L'exemple posté est complet, je l'ai coupé de mon projet et j'utilise eureka et RestTemplate. Ce test peut vous donner ce que vous voulez. Un pas de plus de ce test consiste à écrire un test d'intégration ** réel ** via ruby-concombre ou d'autres technologies liées au contrôle qualité et à exécuter ces tests dans un environnement de test avec un service actif A, service B et service eureka – barbakini

0

Je face à la même problème hier et pour être complet, voici ma solution:

Ceci est ma configuration « live » sous src/main/java/.../config:

//the regular configuration not active with test profile 
@Configuration 
@Profile("!test") 
public class WebConfig { 
    @LoadBalanced 
    @Bean 
    RestTemplate restTemplate() { 
     //you can use your regular rest template here. 
     //This one adds a X-TRACE-ID header from the MDC to the call. 
     return TraceableRestTemplate.create(); 
    } 
} 

J'ai ajouté cette configuration dans le dossier de test src/main/test/java/.../config:

//the test configuration 
@Configuration 
@Profile("test") 
public class WebConfig { 
    @Bean 
    RestTemplate restTemplate() { 
     return TraceableRestTemplate.create(); 
    } 
} 

Dans le cas de test, j'activé le profil test:

//... 
@ActiveProfiles("test") 
@RunWith(SpringRunner.class) 
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 
public class ServerCallTest { 
    @Autowired 
    private IBusiness biz; 

    @Autowired 
    private RestTemplate restTemplate; 

    private ClientHttpRequestFactory originalClientHttpRequestFactory; 

    @Before 
    public void setUp() { 
     originalClientHttpRequestFactory = restTemplate.getRequestFactory(); 
    } 

    @After 
    public void tearDown() { 
     restTemplate.setRequestFactory(originalClientHttpRequestFactory); 
    } 

    @Test 
    public void fetchAllEntries() throws BookListException { 
     MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate); 

     mockServer     
      .andExpect(method(HttpMethod.GET)) 
      .andExpect(header("Accept", "application/json")) 
      .andExpect(requestTo(endsWith("/list/entries/"))) 
      .andRespond(withSuccess("your-payload-here", MediaType.APPLICATION_JSON)); 

     MyData data = biz.getData(); 

     //do your asserts 
    } 
}