web-dev-qa-db-ja.com

Apache Camelで本番ルートを単体テストする方法は?

別のRouteBuilderクラスでルートを作成したとしましょう。次のようになります。

  • jMSキューからメッセージを取得します
  • 変換、検証などを行います
  • 検証結果に応じて特定のJMSキューに転送し、DBに何かを保存します

このルートをJMSブローカーとDBなしで単体テストしたいと思います。プロセッサの実装をモックできることは知っていますが、それだけでは十分ではありません。このルートを変更したくありません(jarファイルでそのクラスを取得したとしましょう)。 Camel in Action(sec。6.2.6)から知る限り、エンドポイントのモックやその他のものを使用できるようにするには、ルートエンドポイント定義を変更する必要があります(本の例では、これは「mina:tcp:/」の変更です。/miranda "から" mock:miranda "など)。

ルート定義を変更せずに、フローを完全に分離してテストすることは可能ですか? RouteBuilderを別のクラスとして取得した場合、どういうわけかルート定義を「コピー」して手動で変更する必要がありますか?それは間違ったことをテストしていませんか?

私はCamelにまったく慣れていないので、ルートを開発しながら単体テストを実行できるのは本当に素晴らしいことです。何かを変更できるようにするために、小さなテストを実行したり、結果を観察したりします。

20
veilsoen

RouteBuilderクラスにエンドポイントがハードコードされていると仮定すると、テストが少し難しくなります。ただし、RouteBuilderがエンドポイントURIにプロパティプレースホルダーを使用している場合は、多くの場合、単体テストに別のエンドポイントURIのセットを使用できます。キャメルの本の第6章で説明されているように。

それらがハードコーディングされている場合は、ここに示すように、単体テストの機能を備えたアドバイスを使用できます: http://camel.Apache.org/advicewith.html

Camel 2.7では、ルートの操作がはるかに簡単になり、パーツの取り外しや交換などができるようになりました。これが、リンクで説明されている織り方です。

たとえば、データベースエンドポイントへのメッセージの送信をシミュレートするには、上記のtoを使用して、代わりにモックに送信する別のtoに置き換えることができます。

以前のリリースでは、interceptSendToEndpointトリックを使用できます。これは、Camelブック(セクション6.3.3)でも説明されています。

169ページに示すように、コンポーネントをモックコンポーネントに置き換えることもできます。Camel2.8以降では、モックコンポーネントは認識できないURIパラメータについて文句を言うことはなくなりました。つまり、コンポーネントごとのレベルで、コンポーネントをモックに置き換えるのがはるかに簡単です。

24
Claus Ibsen

私が持っています

   <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>

springファイルとテストクラスパスのshop.propertiesにstock.out = xxxxがあり、実行時に置き換えられるため、実行時とテスト用に異なるルートを使用する必要があります。

複数の環境での6.1.6ユニットテストのより良い例があります

5
ssmithstone

クラウスイプセンの回答に従って、インターセプトとアドバイスを使用してエンドポイントを交換できますが、テストが本番エンドポイントURIに結合されないように、ルートがEndpointインスタンスを受け入れるようにする方がはるかに良いと思います。 。

たとえば、次のようなRouteBuilderがあるとします。

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

次のようにエンドポイントを挿入できるようにすることができます。

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);
    }
}

次に、次のようにテストできます。

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

これには次の利点があります。

  • テストは非常にシンプルで理解しやすく、CamelTestSupportやその他のヘルパークラスを拡張する必要もありません。
  • CamelContextは手動で作成されるため、テスト対象のルートのみが作成されていることを確認できます。
  • テストは本番ルートのURIを気にしません
  • 必要に応じて、エンドポイントURIをルートクラスにハードコーディングすることもできます。
2
Robert Johnson