junit mocking routes integration apache-camel

junit - ¿Cómo hacer pruebas de unidad de las rutas de producción en Apache Camel?



mocking routes (3)

Digamos que tengo mis rutas creadas en una clase separada de RouteBuilder. Parece que:

  • tomar mensaje de la cola JMS
  • hacer alguna transformación, validación, etc.
  • Dependiendo de los resultados de la validación, enviaremos a la cola JMS específica y guardaremos algo en la base de datos

Me gustaría hacer una prueba de unidad de esta ruta sin ningún agente JMS ni DB. Sé que puedo burlarme de las implementaciones de mi procesador, pero eso no es suficiente. No quiero cambiar esta ruta (supongamos que tengo esa clase en el archivo jar). Por lo que sé de Camel en Acción (sección 6.2.6), para poder usar simulaciones de puntos finales y otras cosas, necesito cambiar las definiciones de mis puntos finales de ruta (en el ejemplo de libro, esto es el cambio de "mina: tcp: / / miranda "a" simulacro: miranda "etc).

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

Soy bastante nuevo en Camel y para mí sería genial poder tener una prueba de unidad aislada mientras desarrollamos rutas. Solo para poder cambiar algo, ejecutar una pequeña prueba, observar el resultado y así sucesivamente.


Si bien puede usar intercepciones y consejos para intercambiar puntos finales según la respuesta de Claus Ibsen, creo que es mucho mejor permitir que sus rutas acepten instancias de puntos finales para que sus pruebas no se acoplen a sus URI de punto final de producción.

Por ejemplo, supongamos que tiene un RouteBuilder que se parece a 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 hacer posible inyectar puntos finales 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 de esta manera:

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 ni siquiera necesita extender CamelTestSupport u otras clases de ayuda.
  • El CamelContext se crea a mano para que pueda estar seguro de que solo se crea la ruta a prueba
  • La prueba no se preocupa por la ruta de producción URIs
  • Todavía tiene la conveniencia de codificar de forma rígida los URI de punto final en la clase de ruta si desea

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

Si están codificados, puede usar el consejo con la función en su prueba de unidad como se muestra aquí: http://camel.apache.org/advicewith.html

En Camel 2.7 hicimos posible manipular la ruta mucho más fácilmente, de modo que puede eliminar partes, reemplazar partes, etc. Eso es lo que se refiere al tejido que se vincula.

Por ejemplo, para simular el envío de un mensaje a un punto final de la base de datos, puede usarlo más arriba y reemplazarlo con otro donde lo envía a un simulacro.

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

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


yo tengo

<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 primavera y luego en shop.properties en la ruta de la clase de prueba tengo un stock.out = xxxx que se reemplaza en tiempo de ejecución para que pueda tener diferentes rutas una para el tiempo de ejecución y otra para la prueba

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