dev2dev 首页 > 资源中心 > 专家Blog > 专家Blog文章
在使用JNDI查找时进行容器外测试
在IDE中测试容器外的控件之后,我产生了许多关于如何测试JdbcControl的疑问,因为它通常使用JNDI数据源来查看其连接。显然,如果您正在进行普通的JUnit测试,那么您将无法访问JNDI树,因此,在尝试测试JdbcControl时,您会获得一个NamingException。 对于JdbcControl(甚至对于控件自身),这个问题实际上并不是唯一的问题。任何使用JNDI查找资源的代码、控件、POJO或其他东西都会遇到这一问题。有许多方法可以解决这个问题。您可以消除测试环境中对JNDI树的需要,或者为您的测试提供一个轻量级JNDI环境,这样查找就会获得成功。 我个人更喜欢后一种方法,因为它在一个更接近于您的应用程序即将使用的环境中进行测试,但两种方法各有利弊。我将使用JdbcControl作为例子来说明这些方法,请记住,这些方法在其他地方也可以应用。
消除对JNDI环境的需要
在这一方法中,要为测试中的代码提供可供替换的资源配置。因为JdbcControl提供了两种获得其连接的方式:ConnectionDataSource属性集或ConnectionDriver属性集。ConnectionDataSource更常用一些,因为它允许在容器中进行查找,这可以提供池化和其他服务。但您可以使用ConnectionDriver在您的测试环境中配置它,这样就根本不再需要进行查找。 以此JdbcControl为例:
@ControlExtension
@JdbcControl.ConnectionDataSource(jndiName = "mySqlDS")
public interface CustomerDB extends JdbcControl {
@JdbcControl.SQL(statement="SELECT ID, NAME FROM CUSTOMER")
Customer[] getCustomers() throws SQLException;
}
使用控件测试容器(ControlTestCase)的标准测试可能如下所示:
public class CustomerDBDriverTestCase
extends ControlTestCase {
@Control
CustomerDB customerDB;
public void setUp() throws Exception {
super.setUp();
}
public void testGetCustomers() throws Exception {
Customer[] c = customerDB.getCustomers();
assertTrue("Expected 2 customers, found " + c.length,
c.length == 2);
}
}
可以对它进行编译,但在运行它时会获得前面提到的NamingException,从而导致失败。可以对此进行补救,将@ConnectionDriver注释放在CustomerDB字段上,并直接指定JDBC驱动程序参数。但这里有一点要补充,您必须以编程方式使JNDI名称为null,或者控件仍然试图找到它但失败了。以下代码清单显示了使用的代码。注意此清单中的两个地方:字段类型已更改为生成的bean(ControlDBBean),setUp()方法调用setConnectionDataSourceJndiName()方法使JNDI名称为null。
public class CustomerDBDriverTestCase
extends ControlTestCase {
@Control
@ConnectionDriver(
databaseDriverClass = "com.mysql.jdbc.Driver",
databaseURL = "jdbc:mysql://localhost:3306/mydb",
userName = "testuser",
password = "testpassword")
CustomerDBBean customerDB;
public void setUp() throws Exception {
super.setUp();
customerDB.setConnectionDataSourceJndiName(null);
}
public void testGetCustomers() throws Exception {
Customer[] c = customerDB.getCustomers();
assertTrue("Expected 2 customers, found " + c.length,
c.length == 2);
}
}
这就是所采用的所有代码,但在运行测试之前,需要进行一些环境设置。您需要将两个jar文件添加到JUnit启动配置的类路径中,这两个jar文件是weblogic.jar和包含DJBC驱动程序的jar文件。要添加这些jar文件,请单击测试用例并选择Run As > Run。在此屏幕上,应该在测试用例的JUnit节点下看到一个启动配置。选择该配置并打开Classpath选项卡。在该选项卡上选择Advanced... 按钮,然后选择Add Classpath Variables,再选择WEBLOGIC_HOME。接下来选择Extend... 按钮,导航到server/lib,最后选择weblogic.jar。

对JDBC驱动程序执行相同的操作,但您可以只将它放在项目的“lib”目录中,并使用Classpath选项卡上的Add JARs...按钮,避免遍历类路径变量序列。 现在,当您运行测试用例时,应该一切运行良好,并且您的控件在连接到数据库时应该不会再遇到麻烦。 注意:关于此方法,我必须给出的一个告戒是,它要求您在测试中引用已生成的控件bean。尽管直到现在这一点仍然没什么问题,但Beehive社区已经在讨论将来消除代码生成需求的可能性,这样控件就可以更容易地与其他框架集成在一起。因为下一代控件根本无法生成那种bean,因此此方法可能无法通过“未来的考验”。关于这一主题的更多细节,请参阅Beehive开发人员邮件列表。
提供一个轻量级JNDI环境
好了,第一个方法虽然费了一些周折,但确实有用。不利的一面是它取决于JdbcControl的特性,但JdbcControl提供了一个建立其连接的非JNDI方法。如果您的控件(或其他代码)没有提供该选项,该怎么办?或者说如果您想在一个非常类似于您的应用程序的环境中进行测试该怎么办?答案是为您的测试提供一个JNDI上下文,并在它在您的应用程序中使用的名称下注册一个资源。 在这个示例中,我使用了来自Tomcat的Apache Naming组件,但是还应该有其他实现。在第一个方法讨论的测试中使用相同的控件。现在,将使用我们自己的测试中的setUp()方法创建一个JNDI环境。注意,此配置可外部化为一个Xml文件,但为了便于演示,我将在测试用例中完全保持其原样。
public class CustomerDBJndiTestCase
extends ControlTestCase {
@Control
CustomerDB customerDB;
public void setUp() throws Exception {
super.setUp();
// Create initial context
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.naming.java.javaURLContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES,
"org.apache.naming");
InitialContext ic = new InitialContext();
// Construct BasicDataSource reference
Reference ref = new Reference("javax.sql.DataSource",
"org.apache.commons.dbcp.BasicDataSourceFactory", null);
ref.add(new StringRefAddr("driverClassName",
"com.mysql.jdbc.Driver"));
ref.add(new StringRefAddr("url",
"jdbc:mysql://localhost:3306/mydb"));
ref.add(new StringRefAddr("username", "testuser"));
ref.add(new StringRefAddr("password", "testpassword"));
ic.rebind("mySqlDS", ref);
}
public void testGetCustomers() throws Exception {
Customer[] c = customerDB.getCustomers();
assertTrue("Expected 2 customers, found " + c.length,
c.length == 2);
}
}
再次提醒,您必须将weblogic.jar添加到启动配置中。此外,必须将添加以下jar文件。与第一个方法类似,我将这些放入我的项目中,并只使用Add JARs...选项,而不是classpath变量。 -commons-collections-3.1.jar -commons-dbcp-1.2.1.jar -commons-pool-1.2.jar -naming-common.jar -naming-java.jar -<your JDBC Driver jar> 我从Tomcat 5.0.28安装中剔除大多数这种jar文件,因为那是最容易找到它们的地方。 现在您的测试应该能够在运行时访问JNDI环境,并像预期的那样工作。注意,在这里,我们不必引用生成的bean。而是只引用控件接口自身,在我们的应用程序中也将采用同样的方式。
原文出处:http://dev2dev.bea.com/blog/hogue/archive/2006/07/outofcontainer_1.html
作者其它文章
|