2010-05-11 112 views
9

我有一個非常簡單的文件觀察器類,它每2秒檢查一次文件是否發生了變化,如果是,則調用onChange方法(void)。 有沒有簡單的方法來檢查在單元測試中onChange方法是否被調用?JUnit:檢查一個無效方法是否被調用

代碼:

public class PropertyFileWatcher extends TimerTask { 
    private long timeStamp; 
    private File file; 

    public PropertyFileWatcher(File file) { 
     this.file = file; 
     this.timeStamp = file.lastModified(); 
    } 

    public final void run() { 
     long timeStamp = file.lastModified(); 

     if (this.timeStamp != timeStamp) { 
      this.timeStamp = timeStamp; 
      onChange(file); 
     } 
    } 

    protected void onChange(File file) { 
     System.out.println("Property file has changed"); 
    } 
} 

測試:

@Test 
public void testPropertyFileWatcher() throws Exception { 
    File file = new File("testfile"); 
    file.createNewFile(); 
    PropertyFileWatcher propertyFileWatcher = new PropertyFileWatcher(file); 

    Timer timer = new Timer(); 
    timer.schedule(propertyFileWatcher, 2000); 

    FileWriter fw = new FileWriter(file); 
    fw.write("blah"); 
    fw.close(); 

    Thread.sleep(8000); 
    // check if propertyFileWatcher.onChange was called 

    file.delete(); 
} 

回答

16

隨着Mockito,您可以驗證的方法是否被調用至少一次/永遠。

看點4 this page

如:

verify(mockedObject, times(1)).onChange(); // times(1) is the default and can be omitted 
+0

您可以使用任何模擬框架而不是僅僅的Mockito。看看EasyMock或jMock並選擇你喜歡的東西。編寫單元測試的經驗法則是,你只應該模擬你可以控制的對象。換句話說,模擬對象應該使用構造函數參數/設置器或參數傳遞給被測方法。通過這個邏輯,你不能嘲笑在被測試的類的方法內創建的靜態調用,最終的或者私有的,或者「新的」對象。 – Kartik 2010-05-11 23:35:41

+0

任何想法如何在EasyMock中做到這一點?我發現缺乏這方面的文件。當我爲PropertyFileWatcher創建一個模擬像這樣:PropertyFileWatcher propertyFileWatcher = createMockBuilder(PropertyFileWatcher.class).withConstructor(file).createMock();並將預期的調用記錄到onChange並重播:propertyFileWatcher.onChange(file);重放(propertyFileWatcher); onChnage方法立即被調用,並且信息被打印到sysout中,但是我只想驗證IF是否調用了該方法 – nkr1pt 2010-05-12 18:26:26

+0

不要使用mockito能夠執行AtomicBoolean解決方案。 – 2012-08-10 08:21:27

4

據我瞭解,你PropertyFileWatcher是爲了被繼承。那麼,爲什麼不像這樣繼承它:

class TestPropertyFileWatcher extends PropertyFileWatcher 
{ 
    boolean called = false; 
    protected void onChange(File file) { 
     called = true; 
    } 
} 

... 
TestPropertyFileWatcher watcher = new TestPropertyFileWatcher 
... 
assertTrue(watcher.called); 
7

這是您的測試的一個簡單的修改。

@Test 
public void testPropertyFileWatcher() throws Exception { 
    final File file = new File("testfile"); 
    file.createNewFile(); 

    final AtomicBoolean hasCalled = new AtomicBoolean(); 
    PropertyFileWatcher propertyFileWatcher = 
     new PropertyFileWatcher(file) 
     { 
     protected void onChange (final File localFile) 
     { 
      hasCalled.set(true); 
      assertEquals(file, localFile); 
     } 
     } 


    Timer timer = new Timer(); 
    timer.schedule(propertyFileWatcher, 2000); 

    FileWriter fw = new FileWriter(file); 
    fw.write("blah"); 
    fw.close(); 

    Thread.sleep(8000); 
    // check if propertyFileWatcher.onChange was called 

    assertTrue(hasCalled.get()); 
    file.delete(); 
} 
+0

我真的很喜歡這個解決方案,因爲它不會增加對模擬框架的依賴;但是嘲笑框架是單元測試的必要條件;這就是爲什麼我接受嘲笑的建議作爲我的問題的接受答案。 – nkr1pt 2010-05-12 17:19:52

+0

@ nkr1pt。肯定會有一個聲譽嘲諷的框架。如果您不是僅限於1.4版本的JDK,請查看jMock。 – 2010-05-12 20:50:35