问题描述
我尝试测试我的 Dao 类,但它为 DbConnection 类返回此错误:
javax.naming.NoInitialContextException:需要在环境或系统属性或应用程序资源文件中指定类名:java.naming.factory.initial
在 java.naming/javax.naming.spi.NamingManager.getinitialContext(NamingManager.java:691)
在 java.naming/javax.naming.InitialContext.getDefaultinitCtx(InitialContext.java:305)
在 java.naming/javax.naming.InitialContext.getURLOrDefaultinitCtx(InitialContext.java:342)
在 java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)
在 model.DbConnection.(DbConnection.java:16)
在 model.DbConnection.getInstance(DbConnection.java:30)
在 model.ProfileManager.ReturnPatientByKey(ProfileManager.java:27)
在 model.ProfileManagerTest.testReturnPatientByKey(ProfileManagerTest.java:32)
在 java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
在 java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
在 java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
在 java.base/java.lang.reflect.Method.invoke(Method.java:564)
....
我的 DbConnection 类:
package model;
import java.sql.Connection;
import java.sql.sqlException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DbConnection {
private DbConnection() {
Context ctx;
try {
ctx = new InitialContext();
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/CheckUpDb");
} catch (NamingException e) {
// Todo Auto-generated catch block
e.printstacktrace();
}
}
public Connection getConnection() throws sqlException {
return ds.getConnection();
}
public static DbConnection getInstance () {
if(db==null) {
return new DbConnection();
}
else {
return db;
}
}
private static DataSource ds;
private static DbConnection db;
}
Web 应用程序中的数据库连接有效,只有测试返回此错误。 我不认为问题出在我的 ProfileManager 类上,因为它只是一个测试示例:
import static org.junit.Assert.assertTrue;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import model.Bean.PatientBean;
class ProfileManagerTest{
private ProfileManager pm;
String fiscal_code;
String user_password;
PatientBean patient;
@BeforeEach
void setUp() throws Exception {
this.pm = new ProfileManager();
fiscal_code = "aaa";
user_password = "bbb";
patient = mock(PatientBean.class);
}
@AfterEach
void tearDown() throws Exception {
}
@Test
void testReturnPatientByKey() {
patient = (PatientBean) pm.ReturnPatientByKey(fiscal_code,user_password);
assertTrue(true);
}
}
解决方法
Web 应用程序中的数据库连接有效,只有测试返回此错误。
这很可能是因为您在服务器配置中声明了数据源,并且服务器为您的 Web 应用程序提供了一个,但您在测试中没有这样做。
在您的服务器文件中进行搜索,您可能会发现类似或类似的内容,具体取决于您使用的服务器:
<Resource name="jdbc/CheckUpDb"
driverClassName="..."
type="..."
url="..."
username="..."
password="..."
/>
这是configure a datasource using JNDI的一种方式。当您的 Web 应用程序运行时,服务器将按名称为您提供此资源。这就是 ctx.lookup("java:comp/env/jdbc/CheckUpDb");
所做的。它要求服务器为其提供该资源。
但是当您运行单元测试时,您是在服务器环境之外运行的。这意味着当您运行测试时,您在服务器中定义的任何资源(例如使用 context.xml
)都不存在。在您的测试中,您必须提供一个数据源并使其可用于您的 JNDI 上下文,以便这行代码可以工作:
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/CheckUpDb");
以下帖子应为您提供为测试设置 JNDI 数据源所需的详细信息:Setting up JNDI Datasource in jUnit
您将看到那里的示例使用名为 Simple-Jndi 的库,它们用于提供 JNDI 上下文并将其配置为包含测试然后尝试按名称检索的数据源。您可以使用任何 JNDI 提供程序,但您必须自己为您的测试设置数据源(在 @BeforeEach
或 @BeforeAll
内),因为在运行单元测试时,您没有 tomcat 服务器为您执行此操作.