2011-04-14 18 views
17

Digamos que tengo mis rutas creadas en una clase separada de RouteBuilder. Parece que:Cómo probar unidades de rutas de producción en Apache Camel?

  • mensaje de agarre de cola JMS
  • hacer alguna transformación, validación, etc.
  • dependiendo de los resultados de la validación con interés cola JMS específica y ahorrar algo en DB

que había gustaría probar la unidad esta ruta sin intermediario JMS y sin DB. Sé que puedo burlarme de las implementaciones de mi procesador, pero eso no es suficiente. No quiero cambiar esta ruta (supongamos que obtuve esa clase en el archivo jar). Por lo que sé de Camel in Action (sección 6.2.6), para poder usar simulaciones de puntos finales y otras cosas, necesito cambiar las definiciones de mi punto final de ruta (en el ejemplo del libro, este es el cambio de "mina: tcp:// miranda "a" burlarse: miranda "etc.).

¿Es posible probar el flujo en completo aislamiento sin cambiar las definiciones de ruta? Si recibí mi RouteBuilder como una clase separada, ¿estoy obligado a "copiar" de alguna manera la definición de ruta y a cambiarla manualmente? ¿No está probando lo incorrecto?

Soy bastante nuevo en Camel y para mí sería genial poder tener una unidad de prueba aislada durante el desarrollo de las rutas. Solo para poder cambiar algo, realizar una pequeña prueba, observar el resultado, etc.

Respuesta

23

Suponiendo que la clase RouteBuilder tiene puntos finales codificados, es un poco más difícil de probar. Sin embargo, si el RouteBuilder utiliza el marcador de posición de propiedad para uris de punto final, a menudo podrá usar un conjunto diferente de uris de punto final para pruebas de unidad. Como se explica en el capítulo 6 del libro de Camel.

Si ellos están codificados a continuación, puede utilizar el asesoramiento con la característica en su unidad de prueba como se muestra aquí: http://camel.apache.org/advicewith.html

En Camel 2.7 nos ha permitido manipular la ruta mucho más fácil, por lo que puede eliminar las partes, reemplace partes, etc. Eso es lo que vincula el tejido.

Por ejemplo, para simular el envío de un mensaje a un punto final de la base de datos, puede usar el anterior y reemplazarlo por otro donde lo envíe a un simulacro.

En versiones anteriores se puede usar el truco interceptSendToEndpoint, que también está cubierto en el libro Camel (sección 6.3.3)

Oh también puede reemplazar componentes con componentes maqueta como se muestra en la página 169. Ahora en camello 2.8 en adelante, el componente simulado ya no se quejará sobre los parámetros uri que desconoce. Eso significa que es mucho más fácil reemplazar los componentes con simulaciones en un nivel por componente.

3

que tienen

<bean id="properties" class="org.apache.camel.component.properties.PropertiesComponent"> 
     <property name="location" value="classpath:shop.properties"/> 
    </bean> 

    <route> 
     <from uri="direct://stock"/> 
     <to uri="{{stock.out}}"/> 
    </route> 

en mi archivo de la primavera y luego en los shop.properties en la ruta de clase de prueba que tengo un stock.out = xxxx, que se sustituye en tiempo de ejecución para que pueda tener diferentes rutas a uno para el tiempo de ejecución y uno para la prueba

hay un mejor ejemplo en 6.1.6 unidad de pruebas en múltiples entornos

0

Aunque se puede usar intercepta y consejos para intercambiar puntos finales según respuesta de Noel Ibsen, creo que es mucho mejor permitir que sus rutas para aceptar Endpoint instancias para que sus pruebas aren' t acoplado a los URI de su punto final de producción.

Por ejemplo, supongamos que tiene un RouteBuilder que se ve algo como

public class MyRoute extends RouteBuilder { 
    @Override 
    public void configure() throws Exception { 
     from("http://someapi/someresource") 
     .process(exchange -> { 
      // Do stuff with exchange 
     }) 
     .to("activemq:somequeue"); 
    } 
} 

Puede que sea posible inyectar criterios de valoración de esta manera:

public class MyRoute extends RouteBuilder { 
    private Endpoint in; 
    private Endpoint out; 

    // This is the constructor your production code can call 
    public MyRoute(CamelContext context) { 
     this.in = context.getEndpoint("http://someapi/someresource"); 
     this.out = context.getEndpoint("activemq:somequeue"); 
    } 

    // This is the constructor your test can call, although it would be fine 
    // to use in production too 
    public MyRoute(Endpoint in, Endpoint out) { 
     this.in = in; 
     this.out = out; 
    } 

    @Override 
    public void configure() throws Exception { 
     from(this.in) 
     .process(exchange -> { 
      // Do stuff with exchange 
     }) 
     .to(this.out); 
    } 
} 

que luego puede ser probado como esto:

public class MyRouteTest { 
    private Endpoint in; 
    private MockEndpoint out; 
    private ProducerTemplate producer; 

    @Before 
    public void setup() { 
     CamelContext context = new DefaultCamelContext(); 

     this.in = context.getEndpoint("direct:in"); 
     this.out = context.getEndpoint("mock:direct:out", MockEndpoint.class); 
     this.producer = context.createProducerTemplate(); 
     this.producer.setDefaultEndpoint(this.in); 

     RouteBuilder myRoute = new MyRoute(this.in, this.out); 
     context.addRoutes(myRoute); 

     context.start(); 
    } 

    @Test 
    public void test() throws Exception { 
     this.producer.sendBody("Hello, world!"); 
     this.out.expectedMessageCount(1); 
     this.out.assertIsSatisfied(); 
    } 
} 

Esto tiene las siguientes ventajas:

  • su prueba es muy simple y fácil de entender, y no necesita ni siquiera para extender CamelTestSupport u otro ayudante de clases
  • la CamelContext se crea con la mano para que pueda estar seguro de que sólo la ruta que se está probando es creado
  • la prueba no se preocupa por las URIs ruta de producción
  • todavía tiene la conveniencia de la codificación dura de los URI de punto final a la clase de ruta si quieres
Cuestiones relacionadas