当我试图模拟下面的方法(方法使用业务逻辑的远程EJB调用)进行Junit测试时,它给出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”,id 1,id 2,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)
型
我相信,虽然我们在test方法中模拟了Context,但它在调用**Whitebox.invokeMethod(ObjectOfsomeMethodClass,“someMethod”,id 1,id 2,map)方法时并没有使用模拟对象,而是试图调用Context ctx = new InitialContext();**原始方法(someMethod)中的方法。
5条答案
按热度按时间piv4azn71#
手工制作
正如
InitialContext
doc所说,您可以使用java.naming.factory.initial
系统属性为InitialContext
对象提供自己的工厂。当代码在应用服务器内部运行时,系统属性由服务器设置。在我们的测试中,我们提供了自己的 JNDI 实现。以下是我的 Mockito 唯一解决方案:我定义了一个自定义的
InitialContextFactory
类,它返回InitialContext
的模拟。您可以根据自己的意愿定制mock,可能是为了在lookup
调用上返回更多的mock。字符串
Spring版本6之前(edit 添加)
另一个编辑:这是5.2中的deprecated,在6.0中被删除。
如果您不介意利用Spring Framework进行测试,以下是他们的简单解决方案:SimpleNamingContextBuilder:
型
可以将其放入
@Before
或@BeforeClass
中。在activate()
之后,jndi数据将从spring dummy中提取。t5zmwmid2#
添加到Jarekczek's答案(谢谢!虽然这是一个老问题,但我想分享我的版本,以防它对某人有帮助。我遇到了同样的问题,人们可能只想在IntialContextFactory实现类中模拟IntialContext,在其他测试或基本测试类中使用这个模拟对象以避免重复是一个更好的主意。
字符串
采用这种方法的原因是,如果有人希望以不同的方式使用数据源或JNDI提供的任何其他资源进行不同的测试,您可以遵循这种方法。应该只为IntialContext创建一个示例,除非一个多线程测试试图同时访问它(不知道为什么要这样做!))。该示例可以在任何地方使用,以获取所需的JNDI对象并按需使用它们。
希望这对你有帮助!
u3r8eeie3#
你可以重构你的代码并提取新方法中的上下文的初始化。
字符串
你的测试代码如下所示:
型
nue99wik4#
截至目前(PowerMock 1.7.4)
使用
PowerMockito.mock(InitialContext.class)
而不是PowerMockito.createMock(InitialContext.class)
创建模拟字符串
不要手动创建InitialContext,而是让PowerMock为您创建。另外,不要创建PowerMock需要对象的间谍。这意味着您需要创建InitialContext示例。
1mrurvl15#
定义以下自定义类
字符串
并声明工厂为
型