我對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. 使用JNDI數據源進行Spring Boot
- 3. 如何在單元測試中模擬Grails中的數據源
- 4. 如何在Spring中使用由Tomcat提供的JNDI數據源?
- 5. 使用jndi查找數據源的JUnit Servlets測試
- 6. 如何在使用mockito的Spring控制器測試中模擬一個字段?
- 7. 測試Node.js,模擬並測試一個需要的模塊?
- 8. Spring中的Autowire JNDI資源
- 9. 時區爲Spring MVC模擬測試
- 10. 如何爲單元測試一個服務模擬一個entityManager
- 11. Spring Webflow 2.3測試:如何模擬流變量的@Autowired字段
- 12. 如何使用OAuth2和模擬測試資源
- 13. 無法運行第二個數據源的Spring JUnit測試
- 14. 我如何在sinatra中設置一個模擬數據庫進行測試?
- 15. 測試:模擬模擬
- 16. 如何使用模擬測試事件
- 17. Spring:通過我的Spring配置中的JNDI使用Tomcat數據源問題?
- 18. 如何模擬測試的電源相關事件
- 19. 如何寫一個測試通過Spring MVC的測試
- 20. 如何在Spring Boot中模擬db連接以進行測試?
- 21. 如何在單元測試中模擬Spring WebClient
- 22. 如何測試模擬方法的第二個參數?
- 23. 茉莉花測試模擬數據或真實系統和數據源?
- 24. 使用Tomcat的數據源 - 如何訪問數據源彈簧JNDI
- 25. JNDI JDBC數據源7
- 26. 如何模擬測試中的失敗
- 27. RSpec控制器測試失敗 - 如何加載模擬數據?
- 28. 如何在指令單元測試中模擬資源
- 29. Spring數據 - MongoDB - JUnit測試
- 30. 如何模擬一個串行端口進行測試
我這樣做了,但我仍然收到異常導致: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