How to unit test a JavaFx property binding? [duplicate] - java

I have a presentation class storing an XYChart.Series object and updating it by observing the model. The Series updating is done by using Platform.runLater(...)
I want to unit-test this, making sure the commands in runLater are performed correctly. How do I tell the unit-test to wait for the runLater commands to be done?
Right now all I do is Thread.Sleep(...) on the test-thread to give the FXApplicationThread the time to complete, but that sounds stupid.

The way I solved it is as follows.
1) Create a simple semaphore function like this:
public static void waitForRunLater() throws InterruptedException {
Semaphore semaphore = new Semaphore(0);
Platform.runLater(() -> semaphore.release());
semaphore.acquire();
}
2) Call waitForRunLater() whenever you need to wait. Because Platform.runLater() (according to the javadoc) execute runnables in the order they were submitted, you can just write within a test:
...
commandThatSpawnRunnablesInJavaFxThread(...)
waitForRunLater(...)
asserts(...)`
which works for simple tests

To have it more in AssertJ style syntax, you can do something like this:
#Test
public void test() throws InterruptedException {
// do test here
assertAfterJavaFxPlatformEventsAreDone(() -> {
// do assertions here
}
}
private void assertAfterJavaFxPlatformEventsAreDone(Runnable runnable) throws InterruptedException {
waitOnJavaFxPlatformEventsDone();
runnable.run();
}
private void waitOnJavaFxPlatformEventsDone() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
Platform.runLater(countDownLatch::countDown);
countDownLatch.await();
}
}

You could use a CountDownLatch which you create before the runLater and count down at the end of the Runnable

Related

Java Future : How to unblock Main thread while executing Aysnc call

When I do async call using ExecutorService, it returns Future Object. Based on the boolean value it returns, I have to log the status of the async call.
But when I try to call the method get method from the future object, it blocks the main thread execution.
Is it possible to unblock the main thread execution?
public class FutureExample {
static HystrixCommand<Boolean> hystrixCommand;
public FutureExample(HystrixCommand<Boolean> hystrixCommand){
FutureExample.hystrixCommand = hystrixCommand;
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
Boolean something = asyncCall();
if(something) {
System.out.println("Future task is done");
}
System.out.println("Don't wait for async call");
}
private static Boolean asyncCall() throws InterruptedException, ExecutionException {
Future<Boolean> response = hystrixCommand.queue(); // Aysnc Call to remote server
return response.get(); //this is blocking main thread
}
}
The good thing about futures is to be able to release threads until the answer arrives.
So I recommend you to use a Future implementation, like CompletableFuture:
final ExecutorService executorService = Executors.newFixedThreadPool(10);
CompletableFuture.supplyAsync(() -> {
try {
return hystrixCommand.queue();
} catch (Exception e) {
return false;
}
}, executorService);
This will work on another thread and when that future is over it will be done.
According to JavaDocs, get() method waits if necessary for the computation to complete, and then retrieves its result.
If you want to get the result once the task is completed, use isDone() function, which returns true if the task completed (normally, exceptionally, etc.). And invoke get() afterwards.
Also, you can use get(long timeout, TimeUnit unit) function to wait only for the given period of time. In this case the main thread will be "unblocked" automatically if either the time is out or the task has completed.
If you need to execute code in the main thread while the async task is running, you will need to redesign your asyncCall method to make it return a future instead.
An example:
private static Future<Boolean> asyncCall()
throws InterruptedException, ExecutionException {
return hystrixCommand.queue();
}
This way, the main method makes the call regarding when to block/wait:
public static void main(String[] args)
throws InterruptedException, ExecutionException {
Future<Boolean> something = asyncCall();
//do something while async call is running
//to check whether it's done running:
if(something.isDone()) {
System.out.println("Future task is done");
}
//when you're finally ready to wait:
System.out.println("Waiting for async call to finish");
Boolean result = something.get();
}

Most efficient way of calling (in) a new thread

Have the following, rather trivial intention in an JFX application: When a key is pressed on the keyboard and thus a handle(event ev) method is called, I want that something happens in a different, otherwise unused thread.
So far I found to have three options:
Either creating the new thread directly in the handle:
public void handle(KeyEvent ke)
{
new Thread(() -> {
// THE CODE
}).start();
}
}
Or I launch a different thread at programm start looking about like this:
public void run()
{
while(true)
{
if (triggered)
{
// THE CODE
}
}
}
and then in the handle() method, I just set the "triggered" field to true.
The third method would be to create as many instances of a class extending "Thread" as needed to be executed in parallel and use their start() function in the handle().
Well, from what I see, the former method has a significant overhead due to thread creation.
The second method is pointlessly requiring CPU resources 99.9% of the time.
That can only be weakened by adding a sleep() to the loop.
And the third method appears to be quite similar to the first as most resources are allocated when called start(), or am I wrong?
That method also has the downside to have to keep several instances in memmory because I can not preddict how many will be called in parallel.
What solution would you suggest?
Are there other possibilities?
Huge thanks in advance!
I suggest adding the task to an ExecutorService This works as a background thread pool and is idle when not used. The threads in it are reused however to improve efficiency. You can use a cached thread pool if you don't know how many threads at once you will need.
static final ExecutorService executor = Executors.newCachedThreadPool();
public void handle(KeyEvent ke)
{
executor.execute(() -> {
// THE CODE
});
}
or
public void handle(KeyEvent ke)
{
executor.execute(this::task1);
}
void task1()
{
// THE CODE
}
You can use a ThreadPoolExecutor, so you can avoid:
repeatly creating new thread
unnecessarily check triggered status
Like this:
ExecutorService executor = executors.newcachedthreadpool();
public void handle(KeyEvent ke)
{
Runnable runnable = new Runnable() {
void run() {
// code
}
}
executor.execute(runnable);
}
You could either use a JavaFX Service (https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Service.html) or create a Task (https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html) that you submit manually with a new Thread or using an Executor, for example from Executors.newCachedThreadPool().
The alternatives are covered quite well in https://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm.
Based on what you have written I would probably go for the Service, but both alternatives should work.

Sync version of async method

What's the best way to make a synchronous version of an asynchronous method in Java?
Say you have a class with these two methods:
asyncDoSomething(); // Starts an asynchronous task
onFinishDoSomething(); // Called when the task is finished
How would you implement a synchronous doSomething() that does not return until the task is finished?
Have a look at CountDownLatch. You can emulate the desired synchronous behaviour with something like this:
private CountDownLatch doneSignal = new CountDownLatch(1);
void main() throws InterruptedException{
asyncDoSomething();
//wait until doneSignal.countDown() is called
doneSignal.await();
}
void onFinishDoSomething(){
//do something ...
//then signal the end of work
doneSignal.countDown();
}
You can also achieve the same behaviour using CyclicBarrier with 2 parties like this:
private CyclicBarrier barrier = new CyclicBarrier(2);
void main() throws InterruptedException{
asyncDoSomething();
//wait until other party calls barrier.await()
barrier.await();
}
void onFinishDoSomething() throws InterruptedException{
//do something ...
//then signal the end of work
barrier.await();
}
If you have control over the source-code of asyncDoSomething() I would, however, recommend redesigning it to return a Future<Void> object instead. By doing this you could easily switch between asynchronous/synchronous behaviour when needed like this:
void asynchronousMain(){
asyncDoSomethig(); //ignore the return result
}
void synchronousMain() throws Exception{
Future<Void> f = asyncDoSomething();
//wait synchronously for result
f.get();
}

Weird problem using JUnit in multi-thread environment

I meet a weired problem when using JUnit in multi-thread environment. The following code should fail, but it actually pass in eclipse.
public class ExampleTest extends TestCase {
private ExecutorService executor = Executors.newFixedThreadPool(10);
private volatile boolean isDone = false;
public void test() throws InterruptedException, ExecutionException {
executor.submit(new Runnable() {
#Override
public void run() {
try {
fail();
} finally {
isDone = true;
}
}
});
while (!isDone) {
Thread.sleep(1000);
}
}
}
And here'a another piece of code, here I use Future.get() to wait for thread stop, in this case it will fail.
public class ExampleTest extends TestCase {
private ExecutorService executor = Executors.newFixedThreadPool(10);
private volatile boolean isDone = false;
public void test() throws InterruptedException, ExecutionException {
Future future=executor.submit(new Runnable() {
#Override
public void run() {
try {
fail();
} finally {
isDone = true;
}
}
});
future.get();
}
}
I googled it and found that JUnit can not handle Multiple-thread unit testing,but what's the differences between these two pieces of code ? Thanks
JUnit cannot see the exceptions that occur in threads other than the thread in which the tests are running. In the first case, through an exception occurs by calling fail, it occurs in a separate thread run by the executor. Hence it is not visible to JUnit and the test passes.
In the second case, the same exception happens in the separate thread run by the executor but the exception is effectively "reported back" to the test thread when you call future.get. This is because future.get throws an ExecutionException if the computation of the future failed due to any exception. JUnit is able to see this exception and hence the test fails.
As #abhin4v has pointed out, the exception in the new thread gets swallowed. You could try providing your own fail-method that syncronises with the top-level thread very much like in your example with get().
But there's no need to use Futures, just write to a shared variable indicating failure and use newThreadId.join(). Apart from that, I'm not aware of any other way of solving this in plain JUnit.
Take a look at http://www.youtube.com/watch?v=wDN_EYUvUq0 (starting at 17:09), it explain problems you can get with JUnit and threads.
I think, that in your case, get() throws a ExecutionException and that's why the second test fails. In the first testcase, jUnit doesn't see the exception.
There is also the interesting fact that Eclipse and IDEA can spawn a VM in their junit test runners and end up calling system.exit() on it. This means if you don't wait properly in the test (as in the case when you sleep above and hope the the task has completed), it can exit unexpectedly. Interesting, but not exactly what you were asking!
see this link for details...

How to write unit test for "InterruptedException"

In attempts of 100% code coverage, I came across a situation where I need to unit test block of code that catches an InterruptedException. How does one correctly unit test this? (JUnit 4 syntax please)
private final LinkedBlockingQueue<ExampleMessage> m_Queue;
public void addMessage(ExampleMessage hm) {
if( hm!=null){
try {
m_Queue.put(hm);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Right before invoking addMessage(), call Thread.currentThread().interrupt(). This will set the "interrupt" status flag on the thread.
If the interrupted status is set when the call to put() is made on a LinkedBlockingQueue, an InterruptedException will be raised, even if no waiting is required for the put (the lock is un-contended).
By the way, some efforts to reach 100% coverage are counter-productive and can actually degrade the quality of code.
Use a mocking library like Easymock and inject a mock LinkedBlockingQueue
i.e.
#Test(expected=InterruptedException.class)
public void testInterruptedException() {
LinkedBlockingQueue queue = EasyMock.createMock(LinkedBlockingQueue.class);
ExampleMessage message = new ExampleMessage();
queue.put(message);
EasyMock.expectLastCall.andThrow(new InterruptedException());
replay(queue);
someObject.setQueue(queue);
someObject.addMessage(msg);
}
As stated above just make use Thread.currentThread().interrupt() if you caught InterruptedException and isn't going to rethrow it.
As for the unit testing. Test this way: Assertions.assertThat(Thread.interrupted()).isTrue();. It both checks that the thread was interrupted and clears the interruption flag so that it won't break other test, code coverage or anything below.
Another option is to delegate dealing with InterruptedException to Guava's Uninterruptibles, so you don't need to write and test your custom code for it:
import static com.google.common.util.concurrent.Uninterruptibles.putUninterruptibly;
private final LinkedBlockingQueue<ExampleMessage> queue;
public void addMessage(ExampleMessage message) {
putUninterruptibly(queue, message);
}
One proper way could be customizing/injecting the ThreadFactory for the executorservice and from within the thread factory, you got the handle of the thread created, then you can schedule some task to interrupt the thread being interested.
Demo code part for the overwrited method "newThread" in ThreadFactory:
ThreadFactory customThreadfactory new ThreadFactory() {
public Thread newThread(Runnable runnable) {
final Thread thread = new Thread(runnable);
if (namePrefix != null) {
thread.setName(namePrefix + "-" + count.getAndIncrement());
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
scheduledExecutorService.schedule(new Callable<String>() {
public String call() throws Exception {
System.out.println("Executed!");
thread.interrupt();
return "Called!";
}
},
5,
TimeUnit.SECONDS);
return thread;
}
}
Then you can use below to construct your executorservice instance:
ExecutorService executorService = Executors.newFixedThreadPool(3,
customThreadfactory);
Then after 5 seconds, an interrupt signal will be sent to the threads in a way each thread will be interrupted once in executorservice.
The example code in the question may be testable by calling Thread.currentThread().interrupt(). However, besides the mentioned problems various methods reset the interrupted flag. An extensive list is for example here: https://stackoverflow.com/a/12339487/2952093. There may be other methods as well.
Assuming waiting implemented as follows should be tested:
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException ex) {
// Set the interrupt flag, this is best practice for library code
Thread.currentThread().interrupt();
throw new RuntimeException(ex);
}
A call to Thread.sleep itself clears the interrupted flag, so it cannot be set in advance. It can be tested using its own test thread as follows:
AtomicBoolean threadInterrupted = new AtomicBoolean(false);
Runnable toBeInterrupted = () -> {
try {
methodUnderTest();
} catch (RuntimeException unused) {
// Expected exception
threadInterrupted.set(true);
}
};
// Execute the in an operation test thread
Thread testThread = new Thread(toBeInterrupted);
testThread.start();
// When the test thread is waiting, interrupt
while (!threadInterrupted.get()) {
if (testThread.getState() == Thread.State.TIMED_WAITING) {
testThread.interrupt();
}
}
// Assert that the interrupted state is re-set after catching the exception
// Must be happening before thread is joined, as this will clear the flag
assertThat(testThread.isInterrupted(), is(true));
testThread.join();

Categories

Resources