2015-04-11 22 views
7

Sto implementando un message translator pattern con Apache Camel, per consumare messaggi da un endpoint RESTful e inviarli a un endpoint AMQP.In un'applicazione Apache Camel, in che modo i test unitari possono iniettare falsi endpoint al posto di quelli reali?

L'applicazione di chiusura è basata su Spring Boot, quindi utilizzo il componente "spring-boot" Camel per integrare i due framework. Come suggerito dalla documentazione in questo link primavera-boot, sto implementando il mio percorso cammello all'interno di una classe -annotated @Configuration che si estende RouteBuilder:

@Component 
public class MyRestToAmqpRouter extends RouteBuilder { 

    @Override 
    public void configure() throws Exception { 

     from("jetty:http://my-restful-url") 
     .process(exchange -> { 
      // convert the message body from JSON to XML, take some 
      // incoming header values and put them in the outgoing 
      // body, etc... 
     }).to("rabbitmq://my-rabbitmq-url"); 

    } 

} 

La mia domanda riguarda come fare per unit-testing questa traduzione, senza bisogno di un vero endpoint RESTful o di un broker RabbitMQ configurato? Ho letto molti esempi online, nonché il libro Camel in Action ... e sembra che l'approccio tipico per il test dell'unità su una rotta Camel sia quello di tagliare e incollare il percorso nel test dell'unità e sostituire uno o più URL dell'endpoint con "mock:whatever".

Immagino che tipo lavori ... ma è terribilmente fragile e la tua suite di test non riconoscerà quando qualcuno in seguito cambia il codice reale senza aggiornare il test dell'unità.

Ho cercato di adattare alcuni esempi di unit test basato primavera-con deride, in questo modo:

@RunWith(CamelSpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = {Application.class}) 
public class MyRestToAmqpRouterTest extends AbstractJUnit4SpringContextTests { 

    @Produce(uri = "jetty:http://my-restful-url") 
    private ProducerTemplate fakeRest; 

    @EndpointInject(uri = "rabbitmq://my-rabbit-url") 
    private MockEndpoint fakeRabbit; 

    @Test 
    @DirtiesContext 
    public void testRouter() throws InterruptedException { 
     fakeRabbit.expectedMessageCount(1); 
     fakeRest.sendBodyAndHeader("", "header-1", "some value"); 
     fakeRabbit.assertIsSatisfied(); 
    } 

} 

mia speranza era che Camel avrebbe preso tali URL endpoint dal test di unità, registrarli come schernisce. .. e quindi utilizzare i mock anziché l'endpoint reale quando il codice reale tenta di utilizzare tali URL.

Tuttavia, non sono sicuro che ciò sia possibile. Quando uso gli URL reali nel test dell'unità ottengo IllegalArgumentException, perché apparentemente non è possibile iniettare un URL "reale" dell'endpoint in un'istanza MockEndpoint (solo URL con prefisso "mock:").

Quando uso l'URL dell'endpoint "mock:..." nel test dell'unità, è inutile perché non c'è nulla che colleghi l'URL dell'endpoint reale nella classe sottoposta a test. In modo che l'URL dell'endpoint reale non venga mai sovrascritto. Quando viene eseguito il codice reale, utilizza solo l'endpoint reale come normale (e l'obiettivo è di essere in grado di eseguire il test senza una dipendenza esterna su RabbitMQ).

Mi manca qualcosa a un livello davvero fondamentale qui? Sembra che ci sarebbe un modo per i test unitari di iniettare percorsi falsi in una classe come questa, in modo che il codice sotto test possa passare da endpoint reali a finti senza nemmeno rendersene conto. In alternativa, suppongo di poter refactoring il mio codice in modo che l'anonimo Processor fosse elevato a una classe standalone ... e quindi potrei unità testare la sua logica di traduzione indipendentemente dalla rotta. Ma sembra solo un test incompleto.

risposta

3

Alcuni suggerimenti su cosa si può fare.

si può leggere il libro Camel di nuovo sui test, e prestare attenzione all'utilizzo di consulenza con

E c'è anche mockEndpointsAndSkip

E si può anche utilizzare il componente stub

Oppure utilizzare segnaposto proprietà nei vostri percorsi, e quindi configurare gli URI di essere finto/stub etc per i test, e utilizzare quelli reali per la produzione

+1

Grazie per la risposta dettagliata, Claus (e per il tuo lavoro su Camel in generale!). Alla fine sono riuscito a mettere insieme una soluzione basata sui segnaposti di proprietà ... anche se alcuni dettagli sono un po 'diversi in un ambiente Spring Boot rispetto al vecchio Spring basato su XML (o addirittura Spring senza Boot basato sull'annotazione). Non che mi stia lamentando, ma dal momento che Spring Boot sta diventando l'approccio raccomandato principale di Pivotal per il nuovo sviluppo di Spring, sarebbe bello vedere altri esempi focalizzati sul Boot nella documentazione accanto agli esempi precedenti di Spring. –

+0

Sì, ci concentreremo e miglioreremo anche su Camel Boot/Spring Boot. Per esempi, a volte puoi esaminare i test unitari di questi componenti per vedere come lo facciamo lì - http://camel.apache.org/camel-boot –