[英]MockEJB - JUnit Mockito - cannot rebind a mock EJB on second unit test
嗨,我有一個與MockEJB有關的問題。 我需要編寫單元測試來測試正在調用EJB的代碼。 我使用Mockito編寫EJB的模擬,並使用MockEJB模擬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);
}
第一個測試運行良好,但是第二個測試系統性地失敗了(mockito說未調用預期的方法)在調試時,我可以看到,第二次嘗試將模擬EJB部署到JNDI時,它沒有部署,並且第一個模擬對象仍然在那里。 因此,實際上第二個測試是從JNDI中提取第一個測試中創建的模擬。 還要注意,如果我單獨運行第二個測試(通過注釋第一個測試),則運行正常。
我的設置和清理方法如下所示:
@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();
}
我真的不明白會發生什么,我的測試看起來與模擬EJB示例非常相似。 有人有主意嗎?
謝謝
是的,我找到了答案……就在昨天! 實際上,它與MockEJB不相關,但是與我的代碼有關,即執行JNDI查找緩存。 這個電話:
NetworkManager manager = NetworkManagerAccessor.getNetworkManager();
像這樣對JNDI查找進行加密:
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;
}
在這些情況下,我發現在測試之外創建模擬並重用它更容易:
private static ServiceToMock serviceMock = mock(ServiceToMock.class);
@BeforeClass
public static void injectServiceSomewhere(){
//...
}
@Before
public void resetServiceMock() {
reset(serviceMock);
}
那應該做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.