簡體   English   中英

單元測試Swing組件

[英]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許可下發布,其任務是簡化軟件測試。 它由各種模塊組成,可與TestNGJUnit一起使用......

注意,一般來說,對UI內容進行單元測試總是很困難,因為你必須嘲笑很多不可用的東西。
因此,開發應用程序(任何類型)時的主要目的始終是嘗試盡可能地將UI內容與主應用程序邏輯分開。 在這里擁有強大的依賴性,使單元測試變得非常困難,基本上是一場噩夢。 這通常通過使用類似MVC類型的方法來實現,在這種方法中,您主要測試控制器類,而視圖類除了構建UI並將其操作和事件委派給控制器之外什么都不做。 這分離了責任並使測試更容易。

此外,您不一定要測試框架提供的內容,例如測試事件是否被正確觸發。 你應該自己測試你正在編寫的邏輯。

檢查uispec4j項目。 這就是我用來測試我的UI的方法。

www.uispec4j.org

我認為測試的問題是揭示了代碼的問題。 決定它是否在調度線程中運行應該不是模型的工作,這是太多的責任。 它應該只是做它的通知工作,讓一個調用組件決定是直接調用它還是調用它。 該組件應該在知道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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM