[英]Unit testing a Swing component
我正在編寫類似TotalCommander的應用程序。 我有一個單獨的文件列表組件,以及它的模型。 模型支持偵聽器並以下列方式發出諸如CurrentDirChanged
等事件的通知:
private void fireCurrentDirectoryChanged(final IFile dir) { if (SwingUtilities.isEventDispatchThread()) for (FileTableEventsListener listener : tableListeners) listener.currentDirectoryChanged(dir); else { SwingUtilities.invokeLater(new Runnable() { public void run() { for (FileTableEventsListener listener : tableListeners) listener.currentDirectoryChanged(dir); } }); } }
我為此寫了一個簡單的測試:
@Test public void testEvents() throws IOException { IFile testDir = mockDirectoryStructure(); final FileSystemEventsListener listener = context.mock(FileSystemEventsListener.class); context.checking(new Expectations() {{ oneOf(listener).currentDirectoryChanged(with(any(IFile.class))); }}); FileTableModel model = new FileTableModel(testDir); model.switchToInnerDirectory(1); }
這不起作用,因為沒有EventDispatchThread
。 有沒有辦法在無頭構建中進行單元測試?
單元測試java swing jmock
看這個 :
FEST是一系列庫,在Apache 2.0許可下發布,其任務是簡化軟件測試。 它由各種模塊組成,可與TestNG或JUnit一起使用......
注意,一般來說,對UI內容進行單元測試總是很困難,因為你必須嘲笑很多不可用的東西。
因此,開發應用程序(任何類型)時的主要目的始終是嘗試盡可能地將UI內容與主應用程序邏輯分開。 在這里擁有強大的依賴性,使單元測試變得非常困難,基本上是一場噩夢。 這通常通過使用類似MVC類型的方法來實現,在這種方法中,您主要測試控制器類,而視圖類除了構建UI並將其操作和事件委派給控制器之外什么都不做。 這分離了責任並使測試更容易。
此外,您不一定要測試框架提供的內容,例如測試事件是否被正確觸發。 你應該自己測試你正在編寫的邏輯。
檢查uispec4j項目。 這就是我用來測試我的UI的方法。
我認為測試的問題是揭示了代碼的問題。 決定它是否在調度線程中運行應該不是模型的工作,這是太多的責任。 它應該只是做它的通知工作,讓一個調用組件決定是直接調用它還是調用它。 該組件應該在知道Swing線程的代碼部分。 該組件應該只知道文件等。
我只和jMock合作了兩天......所以如果有更優雅的解決方案,請原諒。 :)
看起來你的FileTableModel依賴於SwingUtilities ......你考慮過嘲笑你使用的SwingUtilities嗎? 一種聞起來像黑客但會解決問題的方法是創建一個接口,比如ISwingUtilities,並實現一個虛擬類MySwingUtilities,它只是轉發到真正的SwingUtilities。 然后在您的測試用例中,您可以模擬接口並為isEventDispatchThread返回true。
@Test
public void testEventsNow() throws IOException {
IFile testDir = mockDirectoryStructure();
final ISwingUtilities swingUtils = context.mock( ISwingUtilities.class );
final FileSystemEventsListener listener =
context.mock(FileSystemEventsListener.class);
context.checking(new Expectations()
{{
oneOf( swingUtils ).isEventDispatchThread();
will( returnValue( true ) );
oneOf(listener).currentDirectoryChanged(with(any(IFile.class)));
}});
FileTableModel model = new FileTableModel(testDir);
model.setSwingUtilities( swingUtils ); // or use constructor injection if you prefer
model.switchToInnerDirectory(1);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.