第 9 章 使用 JUnit 测试路由


本教程介绍了如何使用 New Camel Test Case 向导为您的路由创建测试案例,然后测试路由。

概述

New Camel Test Case 向导会生成一个样板 JUnit 测试案例。当您创建或修改路由(例如,向它添加更多处理器)时,您应该创建或修改生成的测试案例,以添加特定于您创建或更新的路由的预期和断言。这样可确保测试对路由有效。

目标

在本教程中,您将完成以下任务:

  • 创建 /src/test/ 文件夹,以存储 JUnit 测试案例
  • ZooOrderApp 项目生成 JUnit 测试案例
  • 修改新生成的 JUnit 测试案例
  • 修改 ZooOrderApp 项目的 pom.xml 文件
  • 使用新的 JUnit 测试案例运行 ZooOrderApp
  • 观察输出

先决条件

  1. 要启动此教程,您需要从以下之一生成的 ZooOrderApp 项目:

  2. Project Explorer 中的 ZooOrderApp 项目的 /src/data/ 目录和 /target/messages/ 子目录中删除任何 trace 生成的消息。跟踪生成的消息以 ID- 前缀开头。例如,图 9.1 “跟踪生成的消息” 显示八个 trace 生成的信息:

    图 9.1. 跟踪生成的消息

    tutTraceGenMsgs

    选择批处理中的所有 trace 生成的消息,右键单击并选择 Delete

创建 src/test 文件夹

在为 ZooOrderApp 项目创建 JUnit 测试案例前,您必须为它创建一个包含在构建路径中的文件夹:

  1. Project Explorer 中,右键单击 ZooOrderApp 项目,然后选择 New Folder
  2. New Folder 对话框中,在项目树窗格中,展开 ZooOrderApp 节点并选择 src 文件夹。

    确保 ZooOrderApp/src 出现在 Enter 或选择 parent folder 字段中。

  3. Folder name 中,输入 /test/java

    tutCreateJUnitTestFolder
  4. Finish

    Project Explorer 中,新的 src/test/java 文件夹会出现在 src/main/resources 文件夹下:

    tutTestFolderAdded
  5. 验证构建路径中是否包含新的 /src/test/java 文件夹。

    1. Project Explorer 中,右键单击 /src/test/java 文件夹以打开上下文菜单。
    2. 选择 Build Path 以查看菜单选项:

      菜单选项 Remove from Build Path 验证构建路径中当前是否包含 /src/test/java 文件夹:

      tutJavaFolderOnBldPath

创建 JUnit 测试案例

ZooOrderApp 项目创建一个 JUnit 测试案例:

  1. Project Explorer 中,选择 src/test/java
  2. 右键单击,然后选择 New Camel Test Case

    NewCamTstCaseTut
  3. Camel JUnit Test Case 向导中,确保 Source folder 字段包含 ZooOrderApp/src/test/java。要找到正确的文件夹,请点击 browse button
  4. Package 字段中,输入 tutorial.zooapp.route。此软件包将包括新的测试案例。
  5. test 字段下的 Camel XML 文件中,点 browse button 打开配置为过滤 XML 文件的文件 explorer,然后选择 ZooOrderApp 项目的 blueprint.xml 文件:

    tutCamXMLUnderTst
  6. 点击 确定Name 字段默认为 BlueprintXmlTest

    tutCamJUnitTstPgComplete
  7. Next 打开 Test Endpoints 页面。

    默认情况下,会选择所有端点,并将包含在测试案例中。

  8. Finish

    注意

    如有提示,将 JUnit 添加到构建路径中。

测试的工件添加到项目中,并显示在 src/test/java 下的 Project Explorer 中。实施测试案例的类在工具的 Java 编辑器中打开:

package tutorial.zooapp.route;

import org.apache.camel.EndpointInject;
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
import org.junit.Test;

public class BlueprintXmlTest extends CamelBlueprintTestSupport {

	// TODO Create test message bodies that work for the route(s) being tested
	// Expected message bodies
	protected Object[] expectedBodies = { "<something id='1'>expectedBody1</something>",
			"<something id='2'>expectedBody2</something>" };
	// Templates to send to input endpoints
	@Produce(uri = "file:src/data?noop=true")
	protected ProducerTemplate inputEndpoint;
	@Produce(uri = "direct:OrderFulfillment")
	protected ProducerTemplate input2Endpoint;
	// Mock endpoints used to consume messages from the output endpoints and then perform assertions
	@EndpointInject(uri = "mock:output")
	protected MockEndpoint outputEndpoint;
	@EndpointInject(uri = "mock:output2")
	protected MockEndpoint output2Endpoint;
	@EndpointInject(uri = "mock:output3")
	protected MockEndpoint output3Endpoint;
	@EndpointInject(uri = "mock:output4")
	protected MockEndpoint output4Endpoint;

	@Test
	public void testCamelRoute() throws Exception {
		// Create routes from the output endpoints to our mock endpoints so we can assert expectations
		context.addRoutes(new RouteBuilder() {
			@Override
			public void configure() throws Exception {
				from("file:target/messages/invalidOrders").to(outputEndpoint);
				from("file:target/messages/validOrders/USA").to(output3Endpoint);
				from("file:target/messages/validOrders/Germany").to(output4Endpoint);
			}
		});

		// Define some expectations

		// TODO Ensure expectations make sense for the route(s) we're testing
		outputEndpoint.expectedBodiesReceivedInAnyOrder(expectedBodies);

		// Send some messages to input endpoints
		for (Object expectedBody : expectedBodies) {
			inputEndpoint.sendBody(expectedBody);
		}

		// Validate our expectations
		assertMockEndpointsSatisfied();
	}

	@Override
	protected String getBlueprintDescriptor() {
		return "OSGI-INF/blueprint/blueprint.xml";
	}

}

对于 ZooOrderApp 项目,生成的 JUnit 测试案例不足,它将无法成功运行。您需要修改它以及项目的 pom.xml,如 “修改 BlueprintXmlTest 文件”一节“修改 pom.xml 文件”一节

修改 BlueprintXmlTest 文件

您必须将 BlueprintXmlTest.java 文件修改为:

  • 导入几个支持所需文件功能的类
  • 创建用于保存各种源 .xml 文件的内容的变量
  • 读取源 .xml 文件的内容
  • 定义适当的预期

按照以下步骤修改 BlueprintXmlTest.java 文件:

  1. Project Explorer 中,展开 ZooOrderApp 项目,以公开 BlueprintXmlTest.java 文件:

    tutBlueprintXMLTestProjExp
  2. 打开 BlueprintXmlTest.java 文件。
  3. 在 Java 编辑器中,单击 import org.apache.camel.EndpointInject; 以展开列表。
  4. 添加以粗体文本显示的两行。添加第一行会导致在更新 pom.xml 文件时将解析的错误,如下一节中的指示。

    package tutorial.zooapp.route;
    
    import org.apache.camel.EndpointInject;
    import org.apache.camel.Produce;
    import org.apache.camel.ProducerTemplate;
    import org.apache.camel.builder.RouteBuilder;
    import org.apache.camel.component.mock.MockEndpoint;
    import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
    import org.apache.commons.io.FileUtils;
    import org.junit.Test;
    import java.io.File;
  5. 向下滚动到在 // Expected 消息正文 后直接遵循的行。
  6. 使用这些 受保护的 String body#; 行替换这些行来保护的 Object[] expectedBodies={ …​…​ expectedBody2</something>"}; iwl-DESTINATION to these protected String body"; 行:

    protected String body1; protected String body2; protected String body3; protected String body4; protected String body5; protected String body6;
  7. 向下滚动到行 public void testCamelRoute ()会抛出 Exception {,并在行 body# = FileUtils.readFileToString (new File ("src/data/message#.xml"), "UTF-8") 后插入,如下所示。这些行将指示错误,直到您根据下一节中的指示更新 pom.xml 文件。

    // Valid orders body2 = FileUtils.readFileToString(new File("src/data/message2.xml"), "UTF-8"); body4 = FileUtils.readFileToString(new File("src/data/message4.xml"), "UTF-8"); body5 = FileUtils.readFileToString(new File("src/data/message5.xml"), "UTF-8"); body6 = FileUtils.readFileToString(new File("src/data/message6.xml"), "UTF-8"); // Invalid orders body1 = FileUtils.readFileToString(new File("src/data/message1.xml"), "UTF-8"); body3 = FileUtils.readFileToString(new File("src/data/message3.xml"), "UTF-8");
  8. 向下滚动到 // TODO Ensure expectations 之后直接遵循的行,对我们测试的路由有意义
  9. 将以 outputEndpoint.expectedBodiesReceivedInAnyOrder (expectedBodies)开始的 代码块替换为 …​inputEndpoint.sendBody (expectedBody); },显示的行:

    // Invalid orders outputEndpoint.expectedBodiesReceived(body1, body3); // Valid orders for USA output3Endpoint.expectedBodiesReceived(body2, body5, body6); // Valid order for Germany output4Endpoint.expectedBodiesReceived(body4);

    其余的代码保留原样。

  10. 保存该文件。
  11. 检查您更新的 BlueprintXmlTest.java 文件是否有所需的修改。它应该类似如下:

    package tutorial.zooapp.route;
    
    import org.apache.camel.EndpointInject;
    import org.apache.camel.Produce;
    import org.apache.camel.ProducerTemplate;
    import org.apache.camel.builder.RouteBuilder;
    import org.apache.camel.component.mock.MockEndpoint;
    import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
    import org.apache.commons.io.FileUtils;
    import org.junit.Test;
    import java.io.file;
    
    public class BlueprintXmlTest extends CamelBlueprintTestSupport {
    
    	// TODO Create test message bodies that work for the route(s) being tested
    	// Expected message bodies
    	protected String body1;
    	protected String body2;
    	protected String body3;
    	protected String body4;
    	protected String body5;
    	protected String body6;
    	// Templates to send to input endpoints
    	@Produce(uri = "file:src/data?noop=true")
    	protected ProducerTemplate inputEndpoint;
    	@Produce(uri = "direct:OrderFulfillment")
    	protected ProducerTemplate input2Endpoint;
    	// Mock endpoints used to consume messages from the output endpoints and then perform assertions
    	@EndpointInject(uri = "mock:output")
    	protected MockEndpoint outputEndpoint;
    	@EndpointInject(uri = "mock:output2")
    	protected MockEndpoint output2Endpoint;
    	@EndpointInject(uri = "mock:output3")
    	protected MockEndpoint output3Endpoint;
    	@EndpointInject(uri = "mock:output4")
    	protected MockEndpoint output4Endpoint;
    
    	@Test
    	public void testCamelRoute() throws Exception {
    		// Create routes from the output endpoints to our mock endpoints so we can assert expectations
    		context.addRoutes(new RouteBuilder() {
    			@Override
    			public void configure() throws Exception {
    				// Valid orders
    				body2 = FileUtils.readFileToString(new File("src/data/message2.xml"), "UTF-8");
    				body4 = FileUtils.readFileToString(new File("src/data/message4.xml"), "UTF-8");
    				body5 = FileUtils.readFileToString(new File("src/data/message5.xml"), "UTF-8");
    				body6 = FileUtils.readFileToString(new File("src/data/message6.xml"), "UTF-8");
    
    				// Invalid orders
    				body1 = FileUtils.readFileToString(new File("src/data/message1.xml"), "UTF-8");
    				body3 = FileUtils.readFileToString(new File("src/data/message3.xml"), "UTF-8");
    
    				from("file:target/messages/invalidOrders").to(outputEndpoint);
    				from("file:target/messages/validOrders/USA").to(output3Endpoint);
    				from("file:target/messages/validOrders/Germany").to(output4Endpoint);
    				from("direct:OrderFulfillment").to(output2Endpoint);
    			}
    		});
    
    		// Define some expectations
    
    		// TODO Ensure expectations make sense for the route(s) we're testing
    		// Invalid orders
    		outputEndpoint.expectedBodiesReceived(body1, body3);
    
    		// Valid orders for USA
    		output3Endpoint.expectedBodiesReceived(body2, body5, body6);
    
    		// Valid order for Germany
    		output4Endpoint.expectedBodiesReceived(body4);
    
    		// Validate our expectations
    		assertMockEndpointsSatisfied();
    	}
    
    	@Override
    	protected String getBlueprintDescriptor() {
    		return "OSGI-INF/blueprint/blueprint.xml";
    	}
    
    }

修改 pom.xml 文件

您需要将对 commons-io 项目的依赖添加到 ZooOrderApp 项目的 pom.xml 文件中:

  1. Project Explorer 中,选择位于目标文件夹下的 pom.xml,然后在工具的 XML 编辑器中打开它。
  2. 单击页面底部的 pom.xml 选项卡,以打开文件进行编辑。
  3. 在 < dependencies> 部分的末尾添加以下行:

    <dependency>
           <groupId>commons-io</groupId>
           <artifactId>commons-io</artifactId>
           <version>2.5</version>
           <scope>test</scope>
    </dependency>
  4. 保存该文件。

运行 JUnit 测试

要运行测试:

  1. 切换到 JBoss 透视图以释放更多工作区。
  2. Project Explorer 中,右键单击 ZooOrderApp 项目。
  3. 选择 Run As JUnit Test

    默认情况下,JUnit 视图在边栏中打开。(为了提供更好的视图,请将其拖动到底部,右侧面板显示 控制台服务器和 属性 选项卡。)

    注意

    有时,测试在第一次在项目上运行 JUnit 时失败。重新运行测试会导致成功的结果。

    如果测试成功运行,您会看到如下内容:

    图 9.2. 成功运行 JUnit

    JUnit 成功

    当测试失败时,您会看到如下内容:

    图 9.3. 失败的 JUnit 运行

    JUnit 失败
    注意

    如果您的执行环境没有设置为 Java SE 8,则 JUnit 将失败。JUnit 选项卡顶部的消息栏将显示一条错误消息,表示它无法找到正确的 SDK。

    要解决这个问题,打开项目的上下文菜单,然后选择 Run As Run Configuration JRE。点 *Execution environment 字段旁边的 Environments] 按钮,找到并选择 Java SE 8 环境。

  4. 检查输出并采取措施解决任何测试失败。

    要查看 JUnit 面板中显示的更多错误,请点面板菜单栏中的 Maximize button 来最大化视图。

    再次运行 JUnit 测试案例前,请先从 Project Explorer 中的 ZooOrderApp 项目的 /src/data 文件夹删除任何 JUnit 生成的测试消息(请参阅 图 9.1 “跟踪生成的消息”)。

进一步阅读

要了解有关 JUnit 测试的更多信息,请参阅 JUnit

后续步骤

第 10 章 将项目发布到红帽 Fuse 教程中,您将了解如何将 Apache Camel 项目发布到红帽 Fuse。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.