How to write test cases for ExecutorServices? - java

I have a method which is using ExecutorService to create and execute multiple threads. Code works fine. Now I want to write JUNIT test case for the same.
Code is as below :
private void method(Long input1, object result)
{
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Callable< myObject>> callables = Arrays.asList( callables as List);
try
{
List<Future< myObject>> futures = executor.invokeAll(callables);
executor.shutdown();
for(Future< myObject> f : futures)
{
method(f, result);
}
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I am new to JUnit test cases. I have looked for answers on internet but there are no specific answers to my problem.
I need a help to write test case so that it comes under Jacoco coverage. Thanks in advance.

With the help of PowerMockito you can mock the static method:
Executors.newFixedThreadPool.
ExecutorService executors = Mockito.mock(ExecutorService.class);
Mockito.when(executors.invokeAll()).thenReturn( <list of futures> );
PowerMockito.mockStatic(Executors.class);
PowerMockito.when(Executors.newFixedThreadPool(anyInt())).thenReturn(executors);
Aim to use a real list containing real Future's (if possible).
(Also do not forget to put the correct classes into the #PrepareForTest Annotation)
Whether such a test makes sense depends on what method(f, result); is doing. If we assume its a private method, there is probably no other way of testing/covering it.
Also its probably not a good idea to have the submission of tasks to an ExecutorService and the handling of the results in a blocking method, so consider a refactoring anyway.

Related

Is CompletableFuture followed immediately by a get efficient?

I just found the following code, it supplies an asynchronous task but immediately get the result (so if I understand correctly, it blocks the current thread until the result is available).
Is it efficient ?
public String myMethod() {
CompletableFuture<String> futur = CompletableFuture.supplyAsync(() -> {
// my long call to an external API
return "theResult";
});
try {
return future.get(FUTURE_TIMEOUT_DURATION, TimeUnit.MINUTES);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
If the timeout is handled correctly in the call to the external API, do I need this completable futur ?
Is it ok to simplify the code like this ?
public String myMethod() {
// my long call to an external API
return "theResult";
}
If you doesn't expect any problem with timeout you most probably can remove code related to feature.
There is possibility that code use some threadlocal variables or otherwise relies on being executed in separate thread.

How to mock completablefuture.get()?

This is the method I'm trying to mock:
#VisibleForTesting
public List<Row> processRows2(CompletableFuture future) {
List<Row> rows2 = new ArrayList<>();
try {
DefaultAsyncResultSet beep = (DefaultAsyncResultSet) future.get();
for (Row b : beep.currentPage()) {
rows2.add(b);
}
}
catch (ExecutionException | InterruptedException e) {
LOGGER.error(e);
LOGGER.error(e.getStackTrace());
throw new RuntimeException(e.getMessage() + " - Check thread pool resources are enough, may be too many queries in queue");
}
return rows2;
}
The problem is that when I try to test it with this (currently just trying to get it to run all the way to either success or failure):
#Test
public void processRows2test() {
FeatureDaoImpl gar = new FeatureDaoImpl(connection);
CompletableFuture L = new CompletableFuture();
gar.processRows2(L);
}
It hangs endlessly. My guess is that the future.get() is where it's hanging; I'm not sure. But I'm not sure how to mock that. I've tried this:
#Mock
private CompletableFuture mockFutures;
#Before
public void setUp() {
try {
Mockito.when(mockFutures.get()).thenReturn((AsyncResultSet) mockResultSetFuture);
}
catch (Exception e) {
}
}
But this I feel is not correct. The try catch is because it yells at me about unhandled exceptions on the get(), so I don't know how to get around that.
I have also now tried this:
#Mock
final CompletableFuture<List<String>> mockedFuture = Mockito.mock(CompletableFuture.class);
With the following in the setup:
Mockito.doReturn(new ArrayList<Row>()).when(mockedFuture).get();
But it still hangs endlessly.
I've seen these:
How to mock completion of a CompletableFuture in Mockito
This one I don't understand what exactly it's trying to get me to do, and doesn't feel super applicable, because it's not a get method. I saw some examples here that have .get() in them... but none were mocked methods unfortunately, they were gets in the test itself: https://www.javatips.net/api/java.util.concurrent.completablefuture
EDIT: the code runs. It returns results. So it isn't that the actual method isn't returning a value - I know it does this, it's doing it in QA right now.
Your current CompletableFuture is not completed, so the .get() method hangs waiting for async completion that will never happen. You can use CompletableFuture.completedFuture(value) to create a CompletableFuture instance that will return the passed value when .get() is called on it.
You can use the CompletableFuture.completedFuture method here
#Test
public void processRows2test() {
FeatureDaoImpl gar = new FeatureDaoImpl(connection);
CompletableFuture L = CompletableFuture.completedFuture(new ArrayList<Row>());
gar.processRows2(L);
}

ExecutorService.execute() silently exits run() method

Trying to test that one of my classes can handle being accessed on multiple threads. I have a JUnit test in which I have created a class to implement Runnable and run my class.
When I run execute, it reaches a line in the run() method and just exits on that thread without reporting back any issue, I've wrapped it with Try-Catch(Throwable), but still no sign of what's gone wrong.
Here's my code:
class ConcurrencyTests {
class ConcurrentComponentTracker implements Runnable {
private String component;
ConcurrentComponentTracker(String component) {
this.component = component;
}
#Override
public void run() {
try {
System.out.printf("Component to track: [%s]\n", component);
ParserHandler parserHandler = new ParserHandler();
System.out.println(parserHandler.componentTracker(component));
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
#Test
void runRunner() {
ExecutorService executor = Executors.newFixedThreadPool(4);
String[] componentsToTrack = {"x", "y", "z"};
executor.execute(new ConcurrentComponentTracker(componentsToTrack[0]));
executor.execute(new ConcurrentComponentTracker(componentsToTrack[1]));
executor.execute(new ConcurrentComponentTracker(componentsToTrack[2]));
}
}
And the output:
Component to track: [x]
Component to track: [y]
Component to track: [z]
It just seems to exit on the ParserHandler instantiation line without reporting anything. When attempting to debug and step into that line, it just skips to the end without letting my inspect the ParserHandler class instantiation.
Whomever answered in a comment and then deleted it solved the problem for me. My main JUnit thread wasn't waiting for the other threads to finish. So I tacked on these lines to the end and it worked as expected:
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
catch (InterruptedException e) {
e.printStackTrace();
}
JUnit test should actually test and verify result. In this particular case your test produces output which should be verified by the developer/tester, thus this is not automation.
I suggest you to use Future<?> to track status of your tasks execution. For Runnable tasks get() method of Future<?> will return null if task executed successfully, otherwise it will forward you exception wrapped with ExecutionException. Code will look like this:
#Test
void runRunner() {
ExecutorService executor = Executors.newFixedThreadPool(3);
String[] componentsToTrack = {"x", "y", "z"};
assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[0]).get());
assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[1]).get());
assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[2]).get());
// cleanup and shutdown pool
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
// ignore this
}
}
Before doing so, you should remove try/catch block inside your run() method.
Another thing you probably can improve is to make executor a field of your test class and manage it with traditional JUnit lifecycle using #BeforeClass, #Before, ... to initialize, clean between tests, shutdown pool gracefully. Bear in mind that thread pools are not so cheap from resources point of view.
Hope it helps!
P.S. if your goal is parallel processing of your ConcurrentComponentTracker's you can store Future<?> in some collection and run assertions after all tasks will be submitted.

JUnit test of a java asyncron method

Today I had to write a method which get a String as a parameter, make a new thread and write it out to the consol after 5 seconds waiting, so something like this:
public void exampleMethod(final String str){
Runnable myRunnable = new Runnable(){
public void run(){
try {
Thread.sleep(5000);
System.out.println(str);
} catch (InterruptedException e) {
//handling of the exception
}
}
};
Thread thread = new Thread(myRunnable);
thread.start();
//some other things to do
}
My question is: How can I test and what should I test in here with JUnit?
Thank you!
There is nothing complex in this method. You are only using standard API-methods: Thread.sleep, System.out.println, ...
The parameter is just printed, you don't modify it nor use it for a calculation or another method.
There are no side-effects to your own written code, just to the STL.
And there is no result of the method, which you could test.
In my opinion it is not necessary and not simply possible to test it.
The only thing you could test (and even that wouldn't be trivial), is, if after an amount of time the String is printed.
[...] JUnit finishes execution while the thread is still alive. There could have been problems down the line, toward the end of that thread's execution, but your test would never reflect it.
The problem lies in JUnit's TestRunner. It isn't designed to look for Runnable instances and wait around to report on their activities. It fires them off and forgets about them. For this reason, multithreaded unit tests in JUnit have been nearly impossible to write and maintain.
Well, the source - this article - is from 2003 and there's no guarantee that this hasn't been fixed yet, but you may try it out yourself.
My suggestion would be:
Run your code and measure the time it takes. Then add some 1000 milliseconds and but a Thread.sleep(executionTime+1000); after you started you asynchronous task. Not that elegant, but should work in practice. If you want more elegance here (and waste less time), you may want to look for framework that provide a solution.
...Or if you start your Thread directly in the test, you may also use Thread.join to wait, but you will have cases, where you aren't able to do that.
EDIT:
Also check this article, which could provide a solution to pipe those errors to the main thread:
public class AsynchTester{
private Thread thread;
private volatile Error error;
private volatile RuntimeException runtimeExc;
public AsynchTester(final Runnable runnable) {
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
runnable.run();
} catch (Error e) {
error = e;
} catch (RuntimeException e) {
runtimeExc = e;
}
}
});
}
public void start() {
thread.start();
}
public void test() throws InterruptedException {
thread.join();
if (error != null)
throw error;
if (runtimeExc != null)
throw runtimeExc;
}
}
Use it like that:
#Test
public void test() throws InterruptedException {
AsynchTester tester = new AsynchTester(new Runnable() {
#Override
public void run() {
//async code
}
});
tester.start();
tester.test();
}
The issue here is that you are trying to test an interaction instead of a simple returned result or a state change. However, that does not mean it can't be done.
The standard out PrintStream can be replaced with System.setOut(). You can inject your own mock implementation that would allow you verify that the String was written to the stream. You just have to be careful, since this changes the global state, it might effect other code or tests that rely on standard output. At a minimum, you will have to put back the original stream. But things might get more complicated if tests are running in parallel.
This takes us to the next issue, the sleep. There isn't a strong guarantee to how long a sleep will block. This means your test would have to provide some buffer to ensure that the thread had time to write the String before checking the state of the mock stream. You don't want your test to be flaky because of some execution timing jitter. So you would have to decide what buffer you would consider acceptable.
An alternative approach would be to change the implementation of the code so that it is easier to test.
The simplest way to do this is to remove all the static dependencies. Instead of explicitly referencing System.out, the class could be initialized with with an PrintStream to write to. Additionally, you could define an interface that would wrap Thread.sleep(). For testing purposes, you can initialize the class with the mock stream and no-op implementation of the sleep interface. However, you may still have some timing issues as you need the newly created thread to execute before continuing the test.
The other thing you can do is take a step back and decide how much you care about this code being tested. There are only 4 interesting lines of code in this sample and none of them are complicated. Having a code review could be sufficient to ensure there are no bugs.
However, if the business logic is more complicate than writing to standard out, you might decided that testing that is important. The good news is that scheduling a task in an executor is straight forward and that is the part that is making the testing hard. You could make an abstraction that encompasses the scheduling of the task in a background thread. Then provide yourself with more direct access to the business logic in order to test that.
I have often solved that, by providing a ResultTarget which implements an interface IResultTarget to the thread,
In productive code the result will be a list that contains the calculation result. (or null)
In your unit test the ResultTarget is the unit test class itself, which then easily can check the received result.
public Interface IResultTarget {
List getResult();
}
public void ThreadTest extends TestCase implements IResultTarget {
List result;
public List getResult(
return this.result;
}
public void testThread() {
MyRunnable myRunnable= new MyRunnable ();
myRunnable.setResultTarget(this);
Thread thread = new Thread(myRunnable);
thread .start();
Thread.sleep(5 * 1000);
// expecting one element as result of the work of myRunnable.
assertEquals(1, result.size());
}
}

Java Executor Best Practices for Tasks that Should Run Forever

I'm working on a Java project where I need to have multiple tasks running asynchronously. I'm led to believe Executor is the best way for me to do this, so I'm familiarizing myself with it. (Yay getting paid to learn!) However, it's not clear to me what the best way is to accomplish what I'm trying to do.
For the sake of argument, let's say I have two tasks running. Neither is expected to terminate, and both should run for the duration of the application's life. I'm trying to write a main wrapper class such that:
If either task throws an exception, the wrapper will catch it and restart the task.
If either task runs to completion, the wrapper will notice and restart the task.
Now, it should be noted that the implementation for both tasks will wrap the code in run() in an infinite loop that will never run to completion, with a try/catch block that should handle all runtime exceptions without disrupting the loop. I'm trying to add another layer of certainty; if either I or somebody who follows me does something stupid that defeats these safeguards and halts the task, the application needs to react appropriately.
Is there a best practice for approaching this problem that folks more experienced than me would recommend?
FWIW, I've whipped-up this test class:
public class ExecTest {
private static ExecutorService executor = null;
private static Future results1 = null;
private static Future results2 = null;
public static void main(String[] args) {
executor = Executors.newFixedThreadPool(2);
while(true) {
try {
checkTasks();
Thread.sleep(1000);
}
catch (Exception e) {
System.err.println("Caught exception: " + e.getMessage());
}
}
}
private static void checkTasks() throws Exception{
if (results1 == null || results1.isDone() || results1.isCancelled()) {
results1 = executor.submit(new Test1());
}
if (results2 == null || results2.isDone() || results2.isCancelled()) {
results2 = executor.submit(new Test2());
}
}
}
class Test1 implements Runnable {
public void run() {
while(true) {
System.out.println("I'm test class 1");
try {Thread.sleep(1000);} catch (Exception e) {}
}
}
}
class Test2 implements Runnable {
public void run() {
while(true) {
System.out.println("I'm test class 2");
try {Thread.sleep(1000);} catch (Exception e) {}
}
}
}
It's behaving the way I want, but I don't know if there are any gotchas, inefficiencies, or downright wrong-headedness waiting to surprise me. (In fact, given that I'm new to this, I'd be shocked if there wasn't something wrong/inadvisable about it.)
Any insight is welcomed.
I faced a similar situation in my previous project, and after my code blew in the face of an angry customer, my buddies and I added two big safe-guards:
In the infinite loop, catch Errors too, not just exceptions. Sometimes unexcepted things happen and Java throws an Error at you, not an Exception.
Use a back-off switch, so if something goes wrong and is non-recoverable, you don't escalate the situation by eagerly starting another loop. Instead, you need to wait until the situation goes back to normal and then start again.
For example, we had a situation where the database went down and during the loop an SQLException was thrown. The unfortunate result was that the code went through the loop again, only to hit the same exception again, and so forth. The logs showed that we hit the same SQLException about 300 times in a second!! ... this happened intermittently several times with occassional JVM pauses of 5 seconds or so, during which the application was not responsive, until eventually an Error was thrown and the thread died!
So we implemented a back-off strategy, approximately shown in the code below, that if the exception is not recoverable (or is excepted to recover within a matter of minutes), then we wait for a longer time before resuming operations.
class Test1 implements Runnable {
public void run() {
boolean backoff = false;
while(true) {
if (backoff) {
Thread.sleep (TIME_FOR_LONGER_BREAK);
backoff = false;
}
System.out.println("I'm test class 1");
try {
// do important stuff here, use database and other critical resources
}
catch (SqlException se) {
// code to delay the next loop
backoff = true;
}
catch (Exception e) {
}
catch (Throwable t) {
}
}
}
}
If you implement your tasks this way then I don't see a point in having a third "watch-dog" thread with the checkTasks() method. Furthermore, for the same reasons I outlined above, I'd be cautious to just start the task again with the executor. First you need to understand why the task failed and whether the environment is in a stable condition that running the task again would be useful.
Aside to eyeballing it, I generally run Java code against static analysis tools like PMD and FindBugs to look for deeper issues.
Specifically for this code FindBugs didn't like that results1 and results2 are not volatile in the lazy init, and that the run() methods might ignore the Exception because they aren't explicitly being handled.
In general I am a bit leery of the use of Thread.sleep for concurrency testing, preferring timers or terminating states/conditions. Callable might be useful in returning something in the event of a disruption that throws an exception if unable to compute a result.
For some best practices and more food for thought, check out Concurrency in Practice.
how about this
Runnable task = () -> {
try{
// do the task steps here
} catch (Exception e){
Thread.sleep (TIME_FOR_LONGER_BREAK);
}
};
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(task,0, 0,TimeUnit.SECONDS);
have you tried Quartz framework ?

Categories