[英]Junit Testing JNDI InitialContext outside the application server
Context context = new InitialContext();
dataSource = (DataSource) context.lookup("java:comp/env/jdbc/multiDS");
connection = dataSource.getConnection();
Please help me to mock the above code.请帮我模拟上面的代码。
Hi Tom Anderson嗨汤姆安德森
I tried the below code我试过下面的代码
@BeforeClass
public static void setUpClass() throws Exception {
// rcarver - setup the jndi context and the datasource
try {
// Create initial context
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.naming.java.javaURLContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES,
"org.apache.naming");
Context ic = new InitialContext();
ic.createSubcontext("java:");
ic.createSubcontext("java:comp");
ic.createSubcontext("java:comp/env");
ic.createSubcontext("java:comp/env/jdbc");
ic.createSubcontext("java:comp/env/jdbc/multiDS");
// Construct DataSource
OracleConnectionPoolDataSource ds = new OracleConnectionPoolDataSource();
ds.setURL("jdbc:oracle:thin:@g9u0696.houston.hp.com:1525:CRNAD");
ds.setUser("uname");
ds.setPassword("pwd");
} catch (NamingException ex) {
ex.printStackTrace();
}
}
But its giving error as:但它给出的错误是:
com.hp.corona.common.exception.CacheException: org.apache.naming.NamingContext cannot be cast to javax.sql.DataSource
Please help me to test the code i just want connection from JNDI datasource请帮助我测试我只想从 JNDI 数据源连接的代码
The orthodox thing to do here would be to change you code so that the Context
is injected into it (by a dependency injection framework, or manually). 这里要做的正统事情是更改代码,以便将
Context
注入其中(通过依赖注入框架或手动)。 Then, you simply pass in a mock in your unit test. 然后,您只需在单元测试中传入模拟。
If you can't do this, and your code must create the IntialContext
itself, then you will need to set up a fake JNDI implementation into which you can inject mocks. 如果您不能这样做,并且您的代码必须自己创建
IntialContext
,那么您将需要设置一个假的JNDI实现,您可以在其中注入模拟。 If you search the web for in-memory JNDI implementation or mock JNDI implementation , you will find various options, or you could write one yourself. 如果您在Web上搜索内存中的JNDI实现或模拟JNDI实现 ,您将找到各种选项,或者您可以自己编写一个。 Basically, you will need an implementation of
InitialContextFactory
which simply returns a suitable mock, which you then select by setting the java.naming.factory.initial
system property. 基本上,您需要一个
InitialContextFactory
的实现, InitialContextFactory
返回一个合适的mock,然后通过设置java.naming.factory.initial
系统属性来选择。
I had a crack at writing the necessary classes. 我在编写必要的课程时遇到了麻烦。 Here you go:
干得好:
public class MockInitialContextFactory implements InitialContextFactory {
private static final ThreadLocal<Context> currentContext = new ThreadLocal<Context>();
@Override
public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
return currentContext.get();
}
public static void setCurrentContext(Context context) {
currentContext.set(context);
}
public static void clearCurrentContext() {
currentContext.remove();
}
}
public class MockInitialContextRule implements TestRule {
private final Context context;
public MockInitialContextRule(Context context) {
this.context = context;
}
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, MockInitialContextFactory.class.getName());
MockInitialContextFactory.setCurrentContext(context);
try {
base.evaluate();
} finally {
System.clearProperty(Context.INITIAL_CONTEXT_FACTORY);
MockInitialContextFactory.clearCurrentContext();
}
}
};
}
}
Use as follows: 使用方法如下:
public class FooTest {
private final Context context = mock(Context.class);
@Rule
public MockInitialContextRule mockInitialContextRule = new MockInitialContextRule(context);
@Test
public void testName() throws Exception {
// set up stubbings on the context mock
// invoke the code under test
}
}
You can use the Spring implementation, it works like this: 您可以使用Spring实现,它的工作方式如下:
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
[...]
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind("jdbc/myDataSource", myDS);
builder.activate();
This is easily done with Simple-JNDI. 使用Simple-JNDI可以轻松完成。 Create a property file "jdbc/multiDS.properties" in your working directory to configure your datasource with these properties:
在工作目录中创建属性文件“jdbc / multiDS.properties”,以使用以下属性配置数据源:
type=javax.sql.DataSource
driver=org.gjt.mm.mysql.Driver
url=jdbc:mysql://localhost/testdb
user=testuser
password=testing
Then instantiate the context with 然后使用实例化上下文
final Hashtable<String, String> env = new Hashtable<String, String>();
env.put("org.osjava.sj.root", "working_dir");
env.put("org.osjava.sj.jndi.shared", "true");
env.put("java.naming.factory.initial", "org.osjava.sj.SimpleContextFactory");
env.put("org.osjava.sj.delimiter", "/");
env.put("org.osjava.sj.space", "java:comp/env")
Context ctx = new InitialContext(env);
After that you can call 之后你可以打电话
dataSource = (DataSource) context.lookup("java:comp/env/jdbc/multiDS");
Find more info about Simple-JNDI here https://github.com/h-thurow/Simple-JNDI 有关Simple-JNDI的更多信息,请访问https://github.com/h-thurow/Simple-JNDI
I had problems using the suggested solutions on a legacy system I am adding tests to, but I have found that using Mockito.mockConstruction can be a simple approach:我在添加测试的遗留系统上使用建议的解决方案时遇到问题,但我发现使用 Mockito.mockConstruction 可能是一种简单的方法:
public class FooTest {
private final Context mockContext = mock(Context.class);
@Test
public void myTest()
throws NamingException {
try (final MockedConstruction<InitialContext> ignored =
mockConstruction(InitialContext.class,
(mock, context) ->
when(mock.lookup("java:comp/env"))
.thenReturn(mockContext)) {
// Given
when(mockContext.lookup("environmentEntry"))
.thenReturn(desiredResult);
...
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.