tags:

views:

264

answers:

3

I have a very simple filewatcher class which checks every 2 seconds if a file has changed and if so, the onChange method (void) is called. Is there an easy way to check ik the onChange method is getting called in a unit test?

code:

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();
 }
+3  A: 

With Mockito, you can verify whether a method is called at least once/never.

See point 4 in this page:

http://mockito.googlecode.com/svn/branches/1.5/javadoc/org/mockito/Mockito.html

ryanprayogo
You can use any mocking framework and not just mockito. Take a look at EasyMock or jMock and pick what you like. The rule of thumb of writing unit tests is that you should only mock the objects that you can control. In other words, the mock objects should be made available to the class under test using constructor arguments/setters or parameters to your method under test. By this logic, you cannot mock static invocations, final or private, or "new" objects created inside the method of the class under test.
Kartik
Any idea how you can do it in EasyMock? I find the documentation lacking on this. When I create a mock for PropertyFileWatcher like this: PropertyFileWatcher propertyFileWatcher = createMockBuilder(PropertyFileWatcher.class).withConstructor(file).createMock(); and record the expected call to onChange and replay: propertyFileWatcher.onChange(file); replay(propertyFileWatcher); the onChnage method is called right away and info is printed to sysout, but I would just like to verify IF that method was called or not
nkr1pt
+2  A: 

As I understand, your PropertyFileWatcher is meant to be subclassed. So, why not subclass it like this:

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

...
TestPropertyFileWatcher watcher = new TestPropertyFileWatcher
...
assertTrue(watcher.called);
doublep
+1  A: 

Here is a simple modification for your test.

@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();
 }
Alexander Pogrebnyak
I really like this solution because it doesn't add a dependency to a mocking framework; however mocking frameworks are a necessity for unit testing; that's why I'm accepting the mocking suggestion as the accepted answer to my question.
nkr1pt
@nkr1pt. Definitely go with a reputable mocking framework. If you are not confined to 1.4 version of JDK, take a look at jMock.
Alexander Pogrebnyak