JUnit: checking if a void method gets called

37,567

Solution 1

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

See point 4 in this page

eg:

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

Solution 2

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();
 }
Share:
37,567
nkr1pt
Author by

nkr1pt

Java Software Engineer

Updated on September 10, 2020

Comments

  • nkr1pt
    nkr1pt over 2 years

    I have a very simple file watcher 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 if 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:

    @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();
    }
    
  • Kartik
    Kartik over 12 years
    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.
  • nkr1pt
    nkr1pt over 12 years
    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 over 12 years
    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
  • Alexander Pogrebnyak
    Alexander Pogrebnyak over 12 years
    @nkr1pt. Definitely go with a reputable mocking framework. If you are not confined to 1.4 version of JDK, take a look at jMock.
  • Jordi P.S.
    Jordi P.S. over 10 years
    Don't use mockito being able to do the AtomicBoolean solution.
  • Tony
    Tony over 8 years
    The second link is not up to date. you can see this page : Mockito documentation
  • kaybee99
    kaybee99 about 6 years
    Most of these links are broken. Please paraphrase/quote content directly in the answer to avoid redundancy.
  • Sipty
    Sipty over 5 years
    Just letting you know the link is broken.