我对Spring相当陌生,想知道如何创建使用模拟数据源的JUnit测试以及如何使用JNDI上下文来处理这些测试?目前,我的应用程序使用来自tomcat的JNDI上下文来检索连接,并通过该连接从数据库中检索数据。所以我想我需要模拟JNDI调用和数据检索。对于解决这个问题的最佳方法,任何好的指针都会很棒!非常感谢!如何用Spring测试一个模拟的JNDI数据源?
回答
我通常是在单独的文件中定义我的JNDI的依赖,就像datasource-context.xml
:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<jee:jndi-lookup id="dataSource"
jndi-name="java:comp/env/dataSource"
expected-type="javax.sql.DataSource" />
</beans>
因此,在测试资源,我可以创建另一个文件,并定义测试数据源但它适合我,就像datasource-testcontext.xml
:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="org.hsqldb.jdbcDriver"
p:url="jdbc:hsqldb:hsql://localhost:9001"
p:username="sa"
p:password="" />
</beans>
然后在我的测试类I 中使用数据源的测试配置,而不是依赖于JNDI的产品:
@ContextConfiguration({
"classpath*:META-INF/spring/datasource-testcontext.xml",
"classpath*:META-INF/spring/session-factory-context.xml"
})
public class MyTest {
}
如果数据源不是在一个单独的文件仍然可以存根通过JNDI返回的对象定义容易调用:
- 这样的:Injecting JNDI datasources for JUnit Tests outside of a container
- 或使用类中包
org.springframework.mock.jndi
,即。SimpleNamingContextBuilder
(在这个calass的javadoc中有一个例子)。
您可以通过扩展Spring的AbstractDataSource来创建自己的模拟DataSource。
import java.sql.Connection;
import java.sql.SQLException;
import org.springframework.jdbc.datasource.AbstractDataSource;
/**
* Mock implementation of DataSource suitable for use in testing.
*
*
*/
public class MockDataSource extends AbstractDataSource {
private Connection connection;
/**
* Sets the connection returned by javax.sql.DataSource#getConnection()
* and javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
*
* @param connection
*/
public void setConnection(Connection connection) {
this.connection = connection;
}
/*
* (non-Javadoc)
* @see javax.sql.DataSource#getConnection()
*/
public Connection getConnection()
throws SQLException {
return connection;
}
/*
* (non-Javadoc)
* @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
*/
public Connection getConnection(String username, String password)
throws SQLException {
return connection;
}
}
我想将连接的JNDI查找与其余代码分开。将数据源注入数据访问对象(DAO)并使用MockDataSource来测试DAO。
如果我注入数据源,将这种无法消除JNDI查找的需求? – Marco 2011-05-09 20:10:27
它可以。在Spring中有很多方法来获取数据源。一旦你有了它,你可以注入。不过,Spring可以从JNDI读取一个DataSource。 – 2011-05-09 20:30:22
我编辑了您的答案以删除第一行的缩进。现在语法突出显示工作。我希望你不介意。 – 2011-05-09 21:27:20
您可以使用SimpleNamingContextBuilder使可用的JNDI数据源到你的测试:
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind("java:comp/env/jdbc/mydatasource", dataSource);
builder.activate();
这不正是嘲讽数据源,但它确实使现有数据源通过jndi进行测试。
我这样做了,但我仍然收到异常导致:javax.naming.NoInitialContextException:需要在环境或系统属性中,或作为applet参数或应用程序资源文件中指定类名称:java.naming.factory 。初始 – fastcodejava 2012-07-30 00:30:08
可以八方通创建beans.test.xml配置,您首先引用beans.xml中,然后覆盖数据源配置:
的src /主/资源/的beans.xml
<!-- Database configuration -->
<import resource="beans.datasource.jndi.xml" />
src/test/resources/beans.test。XML
<import resource="beans.xml" />
<import resource="beans.datasource.test.xml" />
JUnit测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/beans.test.xml" })
public class ASRTests
{
...
}
在你的JNDI豆,申报参考
<jee:jndi-lookup expected-type="javax.sql.DataSource" id="mysqlDataSource" jndi-name="jdbc/mysql"/>
在您的测试豆,申报数据源
<bean id="mysqlDataSource" ...>
...
</bean>
保持记住移动测试数据源将bean放入测试文件夹。
Spring的org.springframework.jndi.JndiObjectFactoryBean
最适合用于JNDI查找。按照其文档,它允许为基于弹簧的测试用例注入默认值。
请参考下面的弹簧结构(命名为弹簧测试-DB-config.xml中)
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource">
<property name="URL" value="jdbc:oracle:thin:@localhost:1521:XE"/>
<property name="user" value="UNITTEST"/>
<property name="password" value="UNITTEST"/>
</bean>
<bean id="dataSourceFromJndi" class="org.springframework.jndi.JndiObjectFactoryBean">
<!-- Any junk value will suffice as that is always gonna throw NamingException -->
<property name="jndiName" value="jdbc/Ds"/>
<property name="defaultObject" ref="dataSource"/>
</bean>
添加上其它配置文件中定义的豆应指dataSourceFromJndi
豆
<!-- START OF SERVICES -->
<bean class="com.sample.Service" >
<property name="dataSource" ref="dataSourceFromJndi" />
</bean>
的这种方法的优点是可以保存2个不同的DB配置文件 - 一个用于生产,另一个用于单元测试。只需导入正确的一个。测试配置将包含一个默认对象。
Java的配置.....
JUnit测试用例
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {DatabaseConfigStub.class}, loader= AnnotationConfigContextLoader.class)
public class DatabaseConfigTest {
@Autowired
private DataSource datasource;
@Autowired
private JdbcTemplate jdbcTemplate;
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testDataSource() {
assertNotNull(datasource);
assertNotNull(jdbcTemplate);
}
}
DatabaseConfigStub
public class DatabaseConfigStub {
private static final Logger log = Logger.getLogger(DatabaseConfigStub.class);
private static final String DS_NAME = "jdbc/DS_NAME";
@Bean
DataSource dataSource() {
JndiObjectFactoryBean jndiObjectBean = EasyMock.createMock(JndiObjectFactoryBean.class);
jndiObjectBean.setJndiName(DS_NAME);
jndiObjectBean.setResourceRef(true);
jndiObjectBean.setProxyInterfaces(DataSource.class);
EasyMock.expect((DataSource)jndiObjectBean.getObject()).andReturn(new DataSource() {
public <T> T unwrap(Class<T> iface) throws SQLException {
// TODO Auto-generated method stub
return null;
}
public boolean isWrapperFor(Class<?> iface) throws SQLException {
// TODO Auto-generated method stub
return false;
}
public void setLoginTimeout(int seconds) throws SQLException {
// TODO Auto-generated method stub
}
public void setLogWriter(PrintWriter out) throws SQLException {
// TODO Auto-generated method stub
}
public int getLoginTimeout() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public Connection getConnection(String username, String password)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public Connection getConnection() throws SQLException {
// TODO Auto-generated method stub
return null;
}
}
);
EasyMock.replay(jndiObjectBean);
return (DataSource) jndiObjectBean.getObject();
}
@Bean
JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(dataSource());
}
}
您还可以使用简单的JNDI。这是一个内存JNDI实现,用于处理J2EE容器之外的JNDI上下文。它允许您在生产和测试中使用相同的bean定义文件。假设这是你的bean定义中的生产:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/DataSource"/>
</bean>
<bean id="dao" class="my.Dao">
<property name="dataSource" ref="dataSource" />
</bean>
创建一个属性文件这样
type=javax.sql.DataSource
driverClassName=org.gjt.mm.mysql.Driver
url=jdbc:mysql://localhost/testdb
username=user_name
password=password
将简单JNDI和jndi.properties在classpath中一个小的配置文件。然后照常访问您的数据源。
- 1. JNDI数据源和ApplicationModule测试程序
- 2. 如何在Spring中运行JUnit测试注入JBOSS JNDI数据源
- 3. 使用JNDI数据源进行Spring Boot
- 4. 如何在单元测试中模拟Grails中的数据源
- 5. 如何模拟Spring数据和单元测试服务
- 6. 如何在Spring中使用由Tomcat提供的JNDI数据源?
- 7. 如何在Spring中使用WebLogic提供的JNDI数据源?
- 8. 使用jndi查找数据源的JUnit Servlets测试
- 9. 如何迁移Java,Spring项目以使用JNDI数据源
- 10. 如何在使用mockito的Spring控制器测试中模拟一个字段?
- 11. 测试Spring - 没有模拟的REST API
- 12. Spring项目我如何访问JBoss JNDI数据源
- 13. 如何模拟MongoDB对象来测试我的数据模型?
- 14. 测试Node.js,模拟并测试一个需要的模块?
- 15. Robotium测试案例的模拟数据
- 16. 如何使用Spring的jee使用JNDI引用数据源标签
- 17. Spring中的Autowire JNDI资源
- 18. 时区为Spring MVC模拟测试
- 19. 如何为单元测试一个服务模拟一个entityManager
- 20. 使用DBCP和连接参数配置Spring JNDI数据源
- 21. Spring Webflow 2.3测试:如何模拟流变量的@Autowired字段
- 22. 如何使用OAuth2和模拟测试资源
- 23. 无法运行第二个数据源的Spring JUnit测试
- 24. 模拟/测试Mongodb数据库Node.js
- 25. 我如何在sinatra中设置一个模拟数据库进行测试?
- 26. 测试:模拟模拟
- 27. Python单元测试模拟...模拟一个模块语句
- 28. 如何使用模拟测试事件
- 29. iOS模拟器访问测试资源
- 30. 单元测试在AngularJS模拟$资源
我这样做了,但我仍然收到异常导致:javax.naming.NoInitialContextException:需要在环境或系统属性中,或作为applet参数或应用程序资源文件中指定类名称:java.naming.factory .initial – fastcodejava 2012-07-30 00:29:22
@fastcodejava你做了什么?用于JNDI相关配置的单独文件?在测试设置中创建了JNDI上下文?或者使用'SimpleNamingContextBuilder'? – Roadrunner 2012-08-10 18:40:09