原文:http://tianya23.blog.51cto.com/1081650/292315/
Maven运行用于测试中的最佳实践(个人认为,呵呵)
1、创建maven工程
mvn archetype:create -DgroupId=com.yourcompany -DartifactId=myproject -DarchetypeArtifactId=maven-archetype-quickstart
mvn archetype:create -DgroupId=com.alibaba -DartifactId=seleniumdemo02 -DarchetypeArtifactId=maven-archetype-quickstart
让生成工程的标准模板到外面仓库去取
mvn archetype:generate -Pexternal
生成标准的dubbo、roma等的标准工程
mvn scaffold:create
mvn archetype:generate出错
[INFO] ------------------------------------------------------------------------ [ERROR] BUILD ERROR [INFO] ------------------------------------------------------------------------ [INFO] Internal error in the plugin manager executing goal 'org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-5-SNAPSHOT:generate': Unable to load the mojo 'org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-5-SNAPSHOT:generate' in the plugin 'org.apache.maven.plugins:maven-archetype plugin'. A required class is missing: org/codehaus/plexus/util/xml/XmlStreamReader org.codehaus.plexus.util.xml.XmlStreamReader [INFO] ------------------------------------------------------------------------ [INFO] For more information, run Maven with the -e switch [INFO] ------------------------------------------------------------------------ [INFO] Total time: 12 seconds [INFO] Finished at: Mon Oct 12 00:00:15 CST 2009 [INFO] Final Memory: 8M/15M [INFO] ------------------------------------------------------------------------
一条标准得不能再标准的命令,得到的结果却是一对看不懂的出错信息,实在令人沮丧。其实出错的原因很简单,maven-archetype-plugin没有被认为是Maven的核心插件,也就没有在超级POM中为其设定版本,于是,我们运行archetype命令的时候,maven就去中央仓库下载最新的SNAPSHOT,而恰恰这个SNAPSHOT是有问题的,是完全无法工作的,于是我们看到了上面的结果。
解决方案很简单,就是有点烦,我们需要在运行archetype命令的时候指定其版本,命令如下:
mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-4:generate
指定groupId, artifactId, version,2.0-alpha-4是目前的最新版本,试试吧,现在archetype又能正常工作了,他会提示你一大堆可选的archetype类型,我看到了41个之多,个人还是最喜欢默认的 15: internal -> maven-archetype-quickstart () ,在需要一个简单的Maven项目进行测试的时候,非常有用。
2、创建资源文件
maven直接创建出来的工程,是不带resource目录的,使用起来不是非常的方便。
mkdir -p src/{main/java/com/mycompany/webapp,test/java/com/mycompany/webapp,test/resources}
Windows下demo
mkdir src\main\resources,src\test\resources
windows下,创建完整的目录结构
mkdir src\main\java\com\alibaba, src\main\resources, src\test\java\com\alibaba,src\test\resources
3、指定编译级别, 同时注意eclipse的编译级别
<build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <target>1.5</target> <source>1.5</source> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build>
3、在java目录下面写java的代码,在测试下面写集成测试的代码
【注意】测试代码的源代码类的名称中必须以‘Test’开头或者结尾
4、使用mvn执行测试
mvn clean test
5、与页面自动化的程序进行集成
6、Maven实战
一、丰富你的第一个maven2 项目
1. 加入log4j配置文件
在运行测试时你有可能注意到
log4j:WARN No appenders could be found for logger (org.apache.cxf.bus.spring.BusApplicationContext).
log4j:WARN Please initialize the log4j system properly.
这是因为没有加入log4j配置文件的缘故,一般情况下,配置文件应当放在运行时的classpath中,即项目的target目录中。但如果运行mvn clean的话target文件夹将被删去,如果手动拷贝配置文件的话,麻烦不说还有可能造成版本的不一致。此时应当使用maven提供的资源管理功能,即将log4j.properties放在src/main/resources中,maven会自动将该文件放到项目的target目录中(详情参见上文中关于maven 命令lifecycle的讲解),如果配置文件只在测试中被使用可将其放在src/test/resources中。
2. 引入spring管理服务的客户端
将spring的配置文件client-beans.xml放入src/main/resources中,代码详细附录(二)
将org.world.hello.apps.cxf.bookstore.test.BookStoreServiceTest文件中的setUp方法替换为
public void setUp() {
// JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
// factory.getInInterceptors().add(new LoggingInInterceptor());
// factory.getOutInterceptors().add(new LoggingOutInterceptor());
// factory.setServiceClass(BookStore.class);
// factory.setAddress("http://localhost:9000/bookStore");
// setService((BookStore) factory.create());
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[]{"client-beans.xml"});
service = (BookStore)context.getBean("client");
}
并添加import org.springframework.context.support.ClassPathXmlApplicationContext;
启动(/重启)Server,执行mvn test验证一切正常。
你有可能会问‘我并没有在pom.xml中引入spring的包,为什么可以使用spring呢?’;答案在于你所用的包是由maven从repository中下载过来的,其依赖性也由maven所管理,而cxf项目本身便依赖与spring框架,所以spring也被加入到你的classpath中了;你可以从eclipse中看到你的项目依赖于哪些包。
3. 引入spring管理服务的服务端
i. 将项目转变为web项目
创建src/main/webapp/WEB-INF文件夹。
创建文件src/main/webapp/WEB-INF/web.xml,内容如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
</web-app>
创建文件src/main/webapp/index.html,内容如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Insert title here</title>
</head>
<body>
Hello from index.html
</body>
</html>
修改pom.xml,添加以下内容(添加了jetty的maven插件,并指定了在9090端口启动jetty)
<plugins>
……
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<connectors>
<connector
implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>9090</port>
</connector>
</connectors>
</configuration>
</plugin>
……
</plugins>
<finalName>start_off</finalName>
执行命令
$mvn jetty:run
用浏览器访问
你将能看到“Hello from index.html”字样,启动的server可用ctrl+c来停止。
ii. 应用jetty发布服务
修改web.xml,内容如下
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
其中指定了使用WEB-INF/beans.xml作为cxf的配置文件,并将服务挂载在/services/*上。
下面创建WEB-INF/beans.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint address="/bookStore" serviceName="t:bookStoreService"
xmlns:t="http://bookstore.hello.world.org">
<jaxws:implementor>
<bean
class="org.world.hello.apps.cxf.bookstore.server.BookStoreServiceImpl" />
</jaxws:implementor>
<jaxws:inInterceptors>
<bean
class="org.apache.cxf.interceptor.LoggingInInterceptor" />
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean
class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
</jaxws:outInterceptors>
</jaxws:endpoint>
</beans>
其中的jaxws:endpoint指定了服务的终端,address为“/bookStore”表示,服务被发布在 ,serviceName和它的namespace应与在org.world.hello.apps.cxf.bookstore.server.BookStore.java中指定的相同。
jaxws:implementor中指定了服务的实现者。
执行命令
$mvn jetty:run
在 可以看到已发布服务的wsdl。
修改client-beans.xml将proxyFactory的address属性重新指定为“http://127.0.0.1:9090/start_off/services/bookStore”
在另一个命令行
$mvn test
如果通过测试,说明服务已经正常发布在jetty上了。
iii. 将工程打成war包。
在pom.xml中更改打包的格式,即将<packaging>jar</packaging>改为<packaging>war</packaging>。
执行命令
$mvn package
* 注: package 指令在 maven 中的生命期在 test 之后,所以执行 package 时会自动执行 test ,即只有通过了测试才能打包。
执行完打包指令之后,在项目的target目录中就可以看到start_off-1.0.war,要将工程部署在tomcat上,只需将war文件拷贝到webapps文件夹中即可。
二、拆分你的第一个maven2项目为多个子项目的组合
1. 创建子项目
修改pom.xml中的<packaging>war</packaging>为<packaging>pom</packaging>
执行命令(要在同一行中写)
mvn archetype:create -Dversion=1.0 -DgroupId=org.world.hello.apps -DartifactId=start_off_api
执行以上命令后,在start_off项目的pom.xml中会自动添加<modules><module>start_off_api</module></modules>
,表明start_off_api项目为本项目的子项目。
同时在start_off项目的文件夹中会生成start_off_api项目的文件结构。
查看start_off_api项目的pom.xml,也可以看出它和start_off项目的关系。
<parent>
<artifactId>start_off</artifactId>
<groupId>org.world.hello.apps</groupId>
<version>1.0</version>
</parent
执行命令
$mvn eclipse:eclipse
可以发现一条指令同时在操作两个项目。
输出如下结果:
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] ------------------------------------------------------------------------
[INFO] start_off ............................................. SUCCESS [3.734s]
[INFO] start_off_api ......................................... SUCCESS [5.531s]
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9 seconds
[INFO] Finished at: Mon Nov 26 10:24:54 CST 2007
[INFO] Final Memory: 9M/17M
之后可将start_off_api项目也导入eclipse。
同理创建start_off_web项目。
执行命令(要在同一行中写)
mvn archetype:create -Dversion=1.0 -DgroupId=org.world.hello.apps -DartifactId=start_off_web
2. 将逻辑和服务发布分离
将没有用的App.java和AppTest.java删除。
将start_off项目的src/main/webapp文件夹移到start_off_web项目中。
将start_off项目src中的剩余内容移到start_off_api项目的src文件夹中。
注释掉org.world.hello.apps.cxf.bookstore.test. BookStoreServiceTest中的有效测试,添加一个假的测试(目的是跳过maven生命周期的测试阶段,而执行下面任务)
public void testTruth() {
assertTrue( true);
}
修改start_off_web项目的pom.xml文件,修改后的内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>start_off</artifactId>
<groupId>org.world.hello.apps</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.world.hello.apps</groupId>
<artifactId>start_off_web</artifactId>
<name>start_off_web</name>
<version>1.0</version>
<packaging>war</packaging>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.world.hello.apps</groupId>
<artifactId>start_off_api</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<build>
<finalName>start_off_web</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<connectors>
<connector
implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>9090</port>
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
</project>
* 注:其中指出了start_off_web 项目依赖于 start_off_api 项目
修改start_off_api项目的pom.xml文件,修改后的内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>start_off</artifactId>
<groupId>org.world.hello.apps</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.world.hello.apps</groupId>
<artifactId>start_off_api</artifactId>
<name>start_off_api</name>
<version>1.0</version>
<packaging>jar</packaging>
<url>http://maven.apache.org</url>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>
org.world.hello.apps.cxf.bookstore.bin.Server
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
* 注:子项目所依赖的包可从父项目中间接得到
在start_off项目中的pom.xml中删去插件maven-jetty-plugin和maven-jar-plugin。
执行命令
$mvn clean eclipse:clean eclipse:eclipse
$mvn install
以上的install命令,将项目安装到了本地的repository中。
在start_off_web项目的根目录下执行命令mvn jetty:run便可启动服务,wsdl在 。
若想将服务部署到其他server上,可在start_off项目的根目录下执行mvn package,生成的war被放在start_off_web项目的target目录中。
3. 将服务的接口与实现分离
创建start_off_impl子项目,执行命令(要在同一行中写)
mvn archetype:create -Dversion=1.0 -DgroupId=org.world.hello.apps -DartifactId=start_off_impl
将没有用的App.java和AppTest.java删除。
修改start_off_impl项目的pom.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>start_off</artifactId>
<groupId>org.world.hello.apps</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.world.hello.apps</groupId>
<artifactId>start_off_impl</artifactId>
<name>start_off_impl</name>
<version>1.0</version>
<packaging>jar</packaging>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.world.hello.apps</groupId>
<artifactId>start_off_api</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
修改start_off_web项目的pom.xml,添加依赖
<dependency>
<groupId>org.world.hello.apps</groupId>
<artifactId>start_off_impl</artifactId>
<version>1.0</version>
</dependency>
将start_off_api中的
org.world.hello.apps.cxf.bookstore.server. BookStoreServiceImpl.java
org.world.hello.apps.cxf.bookstore.test. BookStoreServiceTest.java
org.world.hello.apps.cxf.bookstore.bin.Server.java
移动到start_off_impl项目中。
在start_off项目的根目录下执行命令
$mvn clean eclipse:clean eclipse:eclipse install
之后便可启动jetty,验证服务仍可访问,项目拆分完毕。