Java MockEJB-JUnit Mockito-无法在第二个单元测试上重新绑定模拟EJB
嗨,我有一个关于MockEJB的问题。我需要编写单元测试来测试调用EJB的代码。我使用Mockito为EJB编写一个mock,并使用MockEJB模拟JNDI上下文 我的测试如下所示:Java MockEJB-JUnit Mockito-无法在第二个单元测试上重新绑定模拟EJB,java,unit-testing,junit,ejb,mockito,Java,Unit Testing,Junit,Ejb,Mockito,嗨,我有一个关于MockEJB的问题。我需要编写单元测试来测试调用EJB的代码。我使用Mockito为EJB编写一个mock,并使用MockEJB模拟JNDI上下文 我的测试如下所示: @Test public void test1() throws Exception { // create a mock instance NetworkManager aMockManager = createMockNetworkManager(); // deploy it in mock
@Test
public void test1() throws Exception {
// create a mock instance
NetworkManager aMockManager = createMockNetworkManager();
// deploy it in mock container and register it in JNDI
registerMockNetworkManager(aMockManager);
// encapsulates the JNDI lookup
NetworkManager manager = NetworkManagerAccessor.getNetworkManager();
// call a method
manager.deleteObject(new TopicId(-1), null, this.userContext);
// verify that the method was called on the mock
verify(aMockManager).deleteObject(new TopicId(-1), null, this.userContext);
}
@Test
public void test2() throws Exception {
// create a mock instance
NetworkManager aMockManager = createMockNetworkManager();
// deploy it in mock container and register it in JNDI
registerMockNetworkManager(aMockManager);
// encapsulates the JNDI lookup
NetworkManager manager = NetworkManagerAccessor.getNetworkManager();
// call a method
manager.deleteDataItem(new DataItemId(-1), null, null, null);
// verify that the method was called on the mock
verify(aMockManager).deleteDataItem(new DataItemId(-1), null, null, null);
}
@Before
public void setupMockJNDI() {
try {
// setup mockEJB
MockContextFactory.setAsInitial();
Context jndiContext = new InitialContext();
// create the mock container
mockContainer = new MockContainer( jndiContext );
} catch (NamingException e) {
e.printStackTrace();
}
}
@After
public void unregisterJNDI() {
// reset mock context
MockContextFactory.revertSetAsInitial();
}
NetworkManagerHome home = (NetworkManagerHome)ServiceLocator.getInstance().getService(NetworkManagerHome.JNDI_NAME, NetworkManagerHome.class);
第一个测试运行良好,但是第二个测试系统性地失败(mockito说没有调用预期的方法)在调试时,我可以看到第二次尝试将模拟EJB部署到JNDI时,它没有部署,并且第一个模拟对象仍然存在因此,事实上,第二个测试是从JNDI生成的,即在第一个测试中创建的模拟。
还请注意,如果我单独运行第二个测试(通过注释第一个测试),它运行良好
我的设置和清理方法如下所示:
@Test
public void test1() throws Exception {
// create a mock instance
NetworkManager aMockManager = createMockNetworkManager();
// deploy it in mock container and register it in JNDI
registerMockNetworkManager(aMockManager);
// encapsulates the JNDI lookup
NetworkManager manager = NetworkManagerAccessor.getNetworkManager();
// call a method
manager.deleteObject(new TopicId(-1), null, this.userContext);
// verify that the method was called on the mock
verify(aMockManager).deleteObject(new TopicId(-1), null, this.userContext);
}
@Test
public void test2() throws Exception {
// create a mock instance
NetworkManager aMockManager = createMockNetworkManager();
// deploy it in mock container and register it in JNDI
registerMockNetworkManager(aMockManager);
// encapsulates the JNDI lookup
NetworkManager manager = NetworkManagerAccessor.getNetworkManager();
// call a method
manager.deleteDataItem(new DataItemId(-1), null, null, null);
// verify that the method was called on the mock
verify(aMockManager).deleteDataItem(new DataItemId(-1), null, null, null);
}
@Before
public void setupMockJNDI() {
try {
// setup mockEJB
MockContextFactory.setAsInitial();
Context jndiContext = new InitialContext();
// create the mock container
mockContainer = new MockContainer( jndiContext );
} catch (NamingException e) {
e.printStackTrace();
}
}
@After
public void unregisterJNDI() {
// reset mock context
MockContextFactory.revertSetAsInitial();
}
NetworkManagerHome home = (NetworkManagerHome)ServiceLocator.getInstance().getService(NetworkManagerHome.JNDI_NAME, NetworkManagerHome.class);
我真的不明白发生了什么,我的测试看起来非常类似于模拟EJB示例。有人有主意吗
谢谢是的,我找到了答案。。。就在昨天!事实上,它与MockEJB无关,而是与我的代码有关,即执行JNDI查找缓存。此电话:
NetworkManager manager = NetworkManagerAccessor.getNetworkManager();
压缩JNDI查找,如下所示:
@Test
public void test1() throws Exception {
// create a mock instance
NetworkManager aMockManager = createMockNetworkManager();
// deploy it in mock container and register it in JNDI
registerMockNetworkManager(aMockManager);
// encapsulates the JNDI lookup
NetworkManager manager = NetworkManagerAccessor.getNetworkManager();
// call a method
manager.deleteObject(new TopicId(-1), null, this.userContext);
// verify that the method was called on the mock
verify(aMockManager).deleteObject(new TopicId(-1), null, this.userContext);
}
@Test
public void test2() throws Exception {
// create a mock instance
NetworkManager aMockManager = createMockNetworkManager();
// deploy it in mock container and register it in JNDI
registerMockNetworkManager(aMockManager);
// encapsulates the JNDI lookup
NetworkManager manager = NetworkManagerAccessor.getNetworkManager();
// call a method
manager.deleteDataItem(new DataItemId(-1), null, null, null);
// verify that the method was called on the mock
verify(aMockManager).deleteDataItem(new DataItemId(-1), null, null, null);
}
@Before
public void setupMockJNDI() {
try {
// setup mockEJB
MockContextFactory.setAsInitial();
Context jndiContext = new InitialContext();
// create the mock container
mockContainer = new MockContainer( jndiContext );
} catch (NamingException e) {
e.printStackTrace();
}
}
@After
public void unregisterJNDI() {
// reset mock context
MockContextFactory.revertSetAsInitial();
}
NetworkManagerHome home = (NetworkManagerHome)ServiceLocator.getInstance().getService(NetworkManagerHome.JNDI_NAME, NetworkManagerHome.class);
ServiceLocator静态地缓存其JNDI查找,以及JNDI上下文:
public Object getService(String jndiName, Class className) {
Object narrowedService = null;
if (cache.containsKey(jndiName)) {
narrowedService = cache.get(jndiName);
} else {
// see J2EE design patterns page 197
synchronized(this) {
try {
Object service = ctx.lookup(jndiName);
narrowedService = PortableRemoteObject.narrow(service, className);
} catch (NamingException ne) {
throw new ServiceLocatorException("Cannot find service : "+jndiName, ne);
}
cache.put(jndiName, narrowedService);
}
}
return narrowedService;
}
因此,解决方案包括在每次测试之前重置此缓存:
Context jndiContext = new InitialContext();
ServiceLocator.getInstance().reset(jndiContext);
// in ServiceLocator :
public void reset(Context c) {
this.cache = new Hashtable<String, Object>();
this.ctx = c;
}
Context jndiContext=new InitialContext();
ServiceLocator.getInstance().reset(jndiContext);
//在ServiceLocator中:
公共无效重置(上下文c){
this.cache=新哈希表();
这个.ctx=c;
}
在这些情况下,我发现在测试之外创建模拟并重用它更容易:
private static ServiceToMock serviceMock = mock(ServiceToMock.class);
@BeforeClass
public static void injectServiceSomewhere(){
//...
}
@Before
public void resetServiceMock() {
reset(serviceMock);
}
应该可以了。您是否尝试重置JNDI上下文?您好,谢谢您的光临!我仍在为此奋斗。重置JNDI上下文是什么意思?在每次测试之前,我试图将其设置为null,但它没有改变任何东西。你还有别的想法吗?