gpt4 book ai didi

java - 如何在单元测试中模拟 InitialContext 构造函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:17:22 32 4
gpt4 key购买 nike

当我尝试为 Junit 测试模拟以下方法(方法使用远程 EJB 调用业务逻辑)时,它给出 javax.naming.NoInitialContextException

private void someMethod(int id1, int id2, HashMap map){
......some code........

Context ctx = new InitialContext();
Object ref = ctx.lookup("com.java.ejbs.MyEJB");

EJBHome ejbHome = (EJBHome)PortableRemoteObject.narrow(ref, EJBHome.class);
EJBBean ejbBean = (EJBBean)PortableRemoteObject.narrow(ejbHome.create(), EJBBean.class);
ejbBean.someMethod(id1,name);

.......some code.......}

我对上述方法的单元测试

@Test
public void testsomeMethod() throws Exception {

.......setting initial code...
//Mock context and JNDI

InitialContext cntxMock = PowerMock.createMock(InitialContext.class);
PowerMock.expectNew(InitialContext.class).andReturn(cntxMock);
expect(cntxMock.lookup("com.java.ejbs.MyEJB")).andReturn(refMock);

..........some code..........

PowerMock.replayAll();
Whitebox.invokeMethod(ObjectOfsomeMethodClass, "someMethod", id1, id2, map);


}

Whitebox.invokeMethod(ObjectOfsomeMethodClass, "someMethod", id1, id2, map) 方法调用时,它给出以下异常。

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
at javax.naming.InitialContext.lookup(InitialContext.java:392)

我相信,虽然我们在测试方法中模拟了 Context,但它在调用 Whitebox.invokeMethod(ObjectOfsomeMethodClass, "someMethod", id1, id2, map) 时并没有使用模拟对象 方法,而不是尝试在原始方法 (someMethod) 中调用 Context ctx = new InitialContext(); 方法。

最佳答案

手工制作

作为InitialContext doc说,您可以使用 java.naming.factory.initial 系统属性为 InitialContext 对象提供自己的工厂。当代码在应用程序服务器内部运行时,系统属性由服务器设置。在我们的测试中,我们提供了我们自己的 JNDI 实现。

这是我的 Mockito 唯一解决方案:我定义了一个自定义 InitialContextFactory 类,它返回 InitialContext 的模拟。您可以根据需要自定义模拟,可能会在 lookup 调用中返回更多模拟。

public class PlainTest {
@Mock InitialContextFactory ctx;
@InjectMocks Klasa1 klasa1;

public static class MyContextFactory implements InitialContextFactory
{
@Override
public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
ConnectionFactory mockConnFact = mock(ConnectionFactory.class);
InitialContext mockCtx = mock(InitialContext.class);
when(mockCtx.lookup("jms1")).thenReturn(mockConnFact);
return mockCtx;
}
}

@Before
public void setupClass() throws IOException
{
MockitoAnnotations.initMocks(this);
System.setProperty("java.naming.factory.initial",
this.getClass().getCanonicalName() + "$MyContextFactory");
}

Spring(由 edit 添加)

如果您不介意利用 Spring Framework 进行测试,这里是他们的简单解决方案:SimpleNamingContextBuilder :

SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
DataSource ds = new DriverManagerDataSource(...);
builder.bind("java:comp/env/jdbc/myds", ds);
builder.activate();

放在@Before@BeforeClass中即可。在activate()之后,将从spring dummy中提取jndi数据。

关于java - 如何在单元测试中模拟 InitialContext 构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36734275/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com