Sven
Sven

Reputation: 1133

Testing threaded code java

I'm working on testing a certain class that utilises a WatchService. This class has a method, processEvents, that works something like this (from http://docs.oracle.com/javase/tutorial/essential/io/notification.html) :

for (;;) {
    WatchKey key;
    try {
        key = watcher.take();
    } catch (InterruptedException x) {
        return;
    }
    for (WatchEvent<?> event: key.pollEvents()) {
        WatchEvent.Kind<?> kind = event.kind();
        // This key is registered only
        // for ENTRY_CREATE events,
        // but an OVERFLOW event can
        // occur regardless if events
        // are lost or discarded.
        if (kind == MODIFY) {
            //Do something
            AddToEvents(event);
        }
    }
    boolean valid = key.reset();
    if (!valid) {
        break;
    }
}

So it has an infinite loop and needs to run in its own thread. Now I'm trying to test the "do something" part, but I'm unsure how. This test method for example shouldn't fail:

@Test
public void testEventAdded() {
    Thread thread = new Thread() {
        @Override
        public void run() {
            synchronized(currentThread) {
                MyClass.processEvents();
            }
        }
    };
    thread.start();
    File tempFile = File.createTempFile("temporary file", null, Paths.get(testdirectory).toFile());
    tempFile.deleteOnExit();
    assertFalse(MyClass.getEvents().isEmpty());
}

Edit: Clarification, getEvents shouldn't be empty(because a file has been created) and this even gets detected by the watchservice (a print gets done). But because it runs in a different thread, the test reports it as being empty, so it fails because isEmpty shouldn't be true in the assertFalse.

Upvotes: 0

Views: 165

Answers (2)

dkatzel
dkatzel

Reputation: 31648

The easiest solution is to only test AddToEvents(event) code in isolation.

Create mock events and then call your AddToEvents(event) and test to make sure you do the right thing.

This has the added benefit of being able to mock events which would be hard to simulate in a real-word environment.

Upvotes: 0

Robin Green
Robin Green

Reputation: 33033

    File tempFile = File.createTempFile("temporary file", null, Paths.get(testdirectory).toFile());
    tempFile.deleteOnExit();
    Thread.sleep(5000);
    assertFalse(MyClass.getEvents().isEmpty());

I guess 5 seconds should be long enough?

Also, you might need to make getEvents synchronized or something.

Upvotes: 1

Related Questions