How to write concurrent unit tests - java

Awaitility is a great tool to unit-test concurrent production code.
Question: Is there a tool to ease writing concurrent test code?
Suppose I wanted to test java.util.concurrent.LinkedBlockingQueue.
public class BlockingQueueTest {
private LinkedBlockingQueue<String> out;
#Before
public void setUp() {
out = new LinkedBlockingQueue<>();
}
#Test
public void putThenGet() throws InterruptedException {
// that's easy because it can be done in one thread
out.put("Hello");
String taken = out.take();
assertThat(taken).isEqualTo("Hello");
}
#Test
public void getBeforePut() throws InterruptedException {
// that's more tricky because it can't be done with one thread
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(() -> {
Thread.sleep(100);
out.put("Hello");
return null;
});
executorService.shutdown();
String taken = out.take();
assertThat(taken).isEqualTo("Hello");
}
}
getBeforePut() is no fun to code. Is there a way to make it less hard and more readable, like so?
#Test
public void getBeforePut2() throws InterruptedException {
// Wanted: DSL for concurrent test-code
Concurrently.sleep(100, TimeUnit.MILLISECONDS).andThen(() -> out.put("Hello"));
String taken = out.take();
assertThat(taken).isEqualTo("Hello");
}

Using TestNG is the easiest way as for me:
#Test(threadPoolSize = 10, invocationCount = 15, timeOut = 1000)
public void testPut(){
out.put("Hello");
}
This test will run 15 times in 10 threads and should take no longer than 1000 ms.
Also you can create tests which depends on other test
#Test(dependsOnMethods = "testPut")
public void testGetAfterPut{
String taken = out.take();
assertThat(taken).isEqualTo("Hello");
}

(A) you can just use Thread without the need of an ExecutorService
#Test
public void getBeforePutWithThread() throws InterruptedException {
new Thread(() -> {
Thread.sleep(100);
out.put("Hello");
}).run();
String taken = out.take();
assertThat(taken).isEqualTo("Hello");
}
(B) You can take this all functionality to a simple function and avoid dependency on external lib
private void runWithDelay(long delay, Runnable action) {
new Thread(() -> {
try {
Thread.sleep(delay);
action.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).run();
}
#Test
public void getBeforePutWithFunction() {
runWithDelay(100, () -> out.put("Hello"));
String taken = out.take();
assertThat(taken).isEqualTo("Hello");
}

By now I'm writing all my tests in kotlin. And with kotlin testing this is easy peasy and fun!
Worth mentioning when testing with threads is JUnit's #Timeout Annotation, which prevents false tests from running infinitely.
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Timeout
import java.util.concurrent.LinkedBlockingQueue
import kotlin.concurrent.thread
class BlockingQueueKotlinTests {
// objectUnderTest
private val out = LinkedBlockingQueue<String>()
#Test
fun `put then get`() {
// that's easy because it can be done in one thread
out.put("Hello")
val taken = out.take()
assertThat(taken).isEqualTo("Hello")
}
#Test
#Timeout(1)
fun `get before put`() {
// thanks to kotlin it's really easy to do that in another thread
thread {
Thread.sleep(100)
out.put("kotlin is great!")
}
val taken = out.take()
assertThat(taken).isEqualTo("kotlin is great!")
}
}

Related

How to cover the missing branch from time delay condition in JUnit

would like to ask for help regarding unit testing my method which sets a time delay. I was only able to cover the half of this method. Here is the method
public void setDelay() {
XMLHandler objXMLHdl = new XMLHandler();
String delay = objXMLHdl.GetXMLValue("myConfig.xml", "/config/WS/delay");
String intDelay = objXMLHdl.GetXMLValue("myConfig.xml", "/config/WS/delay_minutes");
if (delay.equals("1")) {
try {
TimeUnit.MINUTES.sleep(Integer.parseInt(intDelay));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here is the test
public class WSGlobalFunctionsTest {
WSGlobalsFunctions globalFunction = new WSGlobalsFunctions();
XMLHandler objXMLHdl = new XMLHandler();
#Test
public void testSetDelay() {
globalFunction.setDelay();
}
#Test
public void testSetDelayFailed() throws NumberFormatException, InterruptedException, JAXBException {
String delay = objXMLHdl.GetXMLValue("myConfig.xml", "/config/WS/delay");
String intDelay = objXMLHdl.GetXMLValue("myConfig.xml", "/config/WS/delay_minutes");
TimeUnit.MINUTES.sleep(Integer.parseInt(intDelay));
globalFunction.setDelay();
}
Here is the XML file
<config>
<WS>
<delay>0</delay>
<delay_minutes>2</delay_minutes>
</WS>
Any help would be greatly appreciated. T
I'd restructure your code something like this:
interface Sleeper {
void sleep(int minutes);
}
class Delay {
public Delay(XmlHandler objXMLHdl, Sleeper sleeper) {
...
}
public void doDelay() {
String delay = objXMLHdl.GetXMLValue("myConfig.xml", "/config/WS/delay");
String intDelay = objXMLHdl.GetXMLValue("myConfig.xml", "/config/WS/delay_minutes");
if (delay.equals("1")) {
sleeper.sleep(Integer.parseInt(intDelay));
}
}
}
Now you can mock XmlHandler and Sleeper and test your Delay class properly, without your test needing to actually take minutes to run.
You can have a test of normal behaviour where you check that sleep() was called with the correct number of minutes, a case where delay is "0" where you check that sleep() isn't called, and a case where you pass an non-numeric string for intDelay which should throw a NumberFormatException.
You can make your code more testable without changing the interface your clients currently use. Assuming you aren't using any dependency injection framework:
class WSGlobalFunctions {
...
private Delay delay = new Delay(new XmlHandler(), new Sleeper());
...
public void setDelay() {
delay.doDelay();
}
...
}
setDelay is now trivial so you don't need to test it.

Scheduler works incorrect in unit testing

I need to collect data from a public API. I want to collect it daily or twice a day.
public class AlphavantageStockRequestDispatcher {
public static void startAlphavantageStockScraper(int timeInterval) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable getStockList =
new Runnable() {
#Override
public void run() {
List<AlphavantageStock> stocks = AlphavantageStockRequest.getStockPrices(); //Method contains requests
StockDao<AlphavantageStock> dao = new JpaAlphavantageStockDao();
for (AlphavantageStock stock : stocks) {
dao.save(stock);
}
}
};
scheduler.scheduleAtFixedRate(getStockList, 0, timeInterval, TimeUnit.HOURS);
}
}
The problem is when I start it from the same class (just added main method and invoked startAlphavantageStockScraper(1); it works fine. But when I want to test it via JUnit it's not working (test class is in symmetric package name but test subfolder):
public class AlphavantageStockRequestDispatcherTest {
#Test
public void startDispatcher_TwoFullCycles_WithOneHourIntervalBetween() {
AlphavantageStockRequestDispatcher.startAlphavantageStockScraper(1);
}
}
While debugging I found out that in unit test execution a program reaches public void run() line then skips it. So there's no error. Program ends up correctly but does nothing useful.
Any help will be appreciated.
This is how asynchronous programming works. In the AlphavantageStockRequestDispatcher class you've just submitted a task but you have to wait for it's completed. There are several ways to handle this situation. I prefer state notification using java.util.concurrent.CountDownLatch. So some refactoring is recommended in AlphavantageStockRequestDispatcher class like this:
public class AlphavantageStockRequestDispatcher {
public static void startAlphavantageStockScraper(int timeInterval, CountDownLatch latch) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable getStockList =
new Runnable() {
#Override
public void run() {
System.out.println("worker started");
try {
Thread.sleep(10_000L);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("worker finished");
Optional.ofNullable(latch).ifPresent(CountDownLatch::countDown);
}
}
};
scheduler.scheduleAtFixedRate(getStockList, 0, timeInterval, TimeUnit.HOURS);
}
}
Now it's possible to test that.
public class AlphavantageStockRequestDispatcherTest {
#Test
void startDispatcher_TwoFullCycles_WithOneHourIntervalBetween() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
AlphavantageStockRequestDispatcher.startAlphavantageStockScraper(1, latch);
latch.await(20, TimeUnit.SECONDS);
System.out.println("first finished - need some assertions");
}
}

Latch for different task types

I am looking for a java concurrency solution to the following problem.
There are some tasks being run, and a section of code C.
C must wait for all tasks to complete. (With a timeout)
No tasks may commence until C has finished.
I have looked through the java.concurrency package and I found a few things of interest, but nothing seems to work quite right:
Phasers would allow one way blocking, but not two way.
Semaphores, ForkJoinTasks and others have counter-type features but none seem to do what I want.
I believe I could construct something using a phaser and a lock like so:
void C() {
synchronized(lock) {
phaser.awaitAdvanceInterruptibly(phase, 1, TimeUnit.SECONDS);
// Start work anyway if a task is taking too long.
doWork();
}
}
void someTask() {
synchronized(lock) {
phaser.register();
}
doTask().thenRun(
() -> phaser.arriveAndDeregister()
);
}
Now while I'm fairly sure this would work, I'm also aware its a bad idea to try to build your own concurrency solution. Is there a better way of doing this?
If there isn't, what would I use for the phase argument?
Edit: This problem is within a project involving a web client connection, and therefore the tasks arrive unpredictably. However, it is possible that this situation could be avoided by more careful design.
This being a specialized use case, I think we'll need to use multiple concurrency utilities for co-ordination. The below program should do it. Please feel free to post questions of any parts aren't clear -
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class TestClass {
private volatile int numOfActiveTasks = 0;
private Semaphore cSemaphore = new Semaphore(1);
private Semaphore taskSemaphore = new Semaphore(1);
private Object tasksLock = new Object();
//Test method
public static void main(String[] args) throws IOException {
TestClass testClass = new TestClass();
//Launch some task threads
ExecutorService taskES = Executors.newFixedThreadPool(2);
IntStream.range(1, 11).forEach((i) -> taskES.submit(() -> {
try {
testClass.executeTask();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
//Launch some C threads
ExecutorService cES = Executors.newFixedThreadPool(2);
IntStream.range(1, 5).forEach((i) -> cES.submit(() -> {
try {
testClass.C();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
taskES.shutdown();
cES.shutdown();
}
void C() throws InterruptedException {
try {
cSemaphore.acquire();
//If tasks are running, wait at-least n seconds
this.taskSemaphore.tryAcquire(1, TimeUnit.SECONDS);
print("C started running");
doCsWork();
} finally {
cSemaphore.release();
print("C stopped running");
}
}
void executeTask() throws InterruptedException {
//Do not start while C is running
cSemaphore.acquire();
cSemaphore.release();
synchronized (tasksLock) {
++numOfActiveTasks;
taskSemaphore.tryAcquire();
print("A task started running. Total " + numOfActiveTasks + " tasks running");
}
doTasksWork();
synchronized (tasksLock) {
--numOfActiveTasks;
if (numOfActiveTasks == 0) {
taskSemaphore.release();
}
print("A task stopped running. Total " + numOfActiveTasks + " tasks remaining");
}
}
void doCsWork() throws InterruptedException {
Thread.sleep(1000);
}
void doTasksWork() throws InterruptedException {
Thread.sleep(2000);
}
void print(String message) {
System.out.println(message);
}
}
I found a solution for this problem in java.util.concurrent.locks, which is perfect for my use case.
StampedLock lock;
void C() {
long stamp = lock.tryWriteLock(1, TimeUnit.SECONDS);
doWork();
lock.unlockWrite(stamp);
}
void someTask() {
long stamp = lock.readLock();
doTask().thenRun(() -> lock.unlockRead(stamp));
}
The key with the StampedLock class is that the readLock() is not exclusive, whereas the writeLock() is exclusive. It also supports timeouts, similar to the regular Lock.

test multithreading (CompletableFuture) with EasyMock

I would like to add tests for method, which contains CompletableFuture:
public void report(List<String> srcList) {
if (srcList != null) {
...
CompletableFuture.runAsync(() ->
....
srcList.forEach(src-> downloader.send(url)));
}
}
I would like to test, that method send is called. My test looks like:
#Test
public void _test() {
List<String> events = new ArrayList();
events.add("http://xxxx//");
events.add("http://xxxx//");
expect(downloader.send(events.get(0))).andReturn("xxx").times(2);
replay(downloader);
eventReporter.report(events);
verify(downloader);
}
And I get such error Downloader.send("http://xxxx//"): expected: 2, actual: 0
One way to avoid this error, is to set Thread.sleep(100); timeout. Then the thread will wait and verify that the method had called. But this will increase tests time.
Is there other way to test multithreading with EasyMock?
It is a bad practice to unit test asynchronoys code with Thread.sleep() method
because if it even works test will be unstable and flicker (run 3 times 2 pass and 1 fail)
if you set up big time of sleep and write few tests like this you meet a big time of execution
that may be exceed dozens of seconds. For complete this task you need to decouple asynchronous part
of you code from synchronous. Example how to do it:
class Service {
private Downloader downloader;
private ExecutorService service;
public Service (Downloader downloader, ExecutorService service) {
//set variables
}
public void doWork(List<String> list) {
for (String item : list) {
service.submit(() -> {
downloader.download(item);
});
}
}
}
ExecutorService is interface and we need to make our Service that will be synchronous
class SycnronousService impliments ExecutorService {
//methods empty implementations
public void submit(Runnable runnable) {
runnable.run(); //run immediately
}
//methods empty implementations
}
public class ServiceTest {
public void shouldPassAllItemsToDownloader() {
Downloader mockDownloader = AnyMockFramework.mockIt();
Service service = new Service(mockDownloader, new SycnronousService());
List<String> tasks = Arrays.asList("A", "B");
service.doWork(tasks);
verify(mockDownloader).download("A"); //verify in your way with EasyMock
verify(mockDownloader).download("B"); //verify in your way with EasyMock
// no more Timer.sleep() , test runs immeadetely
}
}
You need to replace CompletableFuture to something like in my example, because
unit testing this code not able in this way.
Later in you app you will be able to replace SycnronousService to asynchronous implementation and all will be work as expected.
I agree with #joy-dir 's answer. And you should probably do what she said to simplify your testing.
For the sake of completeness, your problem here is that the verify is called before your tasks being actually finished. There are many things you could do.
One is to loop on verify.
#Test
public void test() throws Exception {
List<String> events = new ArrayList();
events.add("http://xxxx//");
events.add("http://xxxx//");
expect(downloader.send(events.get(0))).andReturn("xxx").times(2);
replay(downloader);
report(events);
for (int i = 0; i < 10; i++) {
try {
verify(downloader);
return;
} catch(AssertionError e) {
// wait until it works
}
Thread.sleep(10);
}
verify(downloader);
}
It won't sleep a long time for nothing when successful. However, you indeed need to make sure you wait enough to prevent the test from being flaky.
Another solution is actually to use the CompletableFuture returned by runAsync. I prefer this solution.
public CompletableFuture<Void> report(List<String> srcList) {
if (srcList != null) {
return CompletableFuture.runAsync(() -> srcList.forEach(src-> downloader.send(src)));
}
return CompletableFuture.completedFuture(null);
}
#Test
public void test2() throws Exception {
List<String> events = new ArrayList();
events.add("http://xxxx//");
events.add("http://xxxx//");
expect(downloader.send(events.get(0))).andReturn("xxx").times(2);
replay(downloader);
CompletableFuture<Void> future = report(events);
future.get(100, TimeUnit.MILLISECONDS);
verify(downloader);
}
Finally, there is a hackish way. You ask the common pool if it is done. It is hackish because something else might use it. So it's cute but I wouldn't really recommend it.
#Test
public void test3() throws Exception {
List<String> events = new ArrayList();
events.add("http://xxxx//");
events.add("http://xxxx//");
expect(downloader.send(events.get(0))).andReturn("xxx").times(2);
replay(downloader);
report(events);
while(!ForkJoinPool.commonPool().isQuiescent()) {
Thread.sleep(10);
}
verify(downloader);
}

Executing Dependent tasks in parallel in Java

I need to find a way to execute tasks (dependent and independent) in parallel in java.
Task A and Task C can run independently.
Task B is dependent on the output of Task A.
I checked java.util.concurrent Future and Fork/Join, but looks like we cannot add dependency to a Task.
Can anyone point me to correct Java API.
In Scala this is very easy to do, and I think you are better off using Scala. Here is an example I pulled from here http://danielwestheide.com/ (The Neophyte’s Guide to Scala Part 16: Where to Go From Here) this guy has a great blog (I am not that guy)
Lets take a barrista making coffee. The tasks to do are:
Grind the required coffee beans (no preceding tasks)
Heat some water (no preceding tasks)
Brew an espresso using the ground coffee and the heated water (depends on 1 & 2)
Froth some milk (no preceding tasks)
Combine the froth milk and the espresso (depends on 3,4)
or as a tree:
Grind _
Coffe \
\
Heat ___\_Brew____
Water \_____Combine
/
Foam ____________/
Milk
In java using the concurrency api this would be:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Barrista {
static class HeatWater implements Callable<String> {
#Override
public String call() throws Exception {
System.out.println("Heating Water");
Thread.sleep(1000);
return "hot water";
}
}
static class GrindBeans implements Callable<String> {
#Override
public String call() throws Exception {
System.out.println("Grinding Beans");
Thread.sleep(2000);
return "grinded beans";
}
}
static class Brew implements Callable<String> {
final Future<String> grindedBeans;
final Future<String> hotWater;
public Brew(Future<String> grindedBeans, Future<String> hotWater) {
this.grindedBeans = grindedBeans;
this.hotWater = hotWater;
}
#Override
public String call() throws Exception
{
System.out.println("brewing coffee with " + grindedBeans.get()
+ " and " + hotWater.get());
Thread.sleep(1000);
return "brewed coffee";
}
}
static class FrothMilk implements Callable<String> {
#Override
public String call() throws Exception {
Thread.sleep(1000);
return "some milk";
}
}
static class Combine implements Callable<String> {
public Combine(Future<String> frothedMilk, Future<String> brewedCoffee) {
super();
this.frothedMilk = frothedMilk;
this.brewedCoffee = brewedCoffee;
}
final Future<String> frothedMilk;
final Future<String> brewedCoffee;
#Override
public String call() throws Exception {
Thread.sleep(1000);
System.out.println("Combining " + frothedMilk.get() + " "
+ brewedCoffee.get());
return "Final Coffee";
}
}
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
FutureTask<String> heatWaterFuture = new FutureTask<String>(new HeatWater());
FutureTask<String> grindBeans = new FutureTask<String>(new GrindBeans());
FutureTask<String> brewCoffee = new FutureTask<String>(new Brew(grindBeans, heatWaterFuture));
FutureTask<String> frothMilk = new FutureTask<String>(new FrothMilk());
FutureTask<String> combineCoffee = new FutureTask<String>(new Combine(frothMilk, brewCoffee));
executor.execute(heatWaterFuture);
executor.execute(grindBeans);
executor.execute(brewCoffee);
executor.execute(frothMilk);
executor.execute(combineCoffee);
try {
/**
* Warning this code is blocking !!!!!!!
*/
System.out.println(combineCoffee.get(20, TimeUnit.SECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
System.out.println("20 SECONDS FOR A COFFEE !!!! I am !##! leaving!!");
e.printStackTrace();
} finally{
executor.shutdown();
}
}
}
Make sure that you add time outs though to ensure that your code will not wait forever on something to complete, that is done by using the Future.get(long, TimeUnit) and then handle failure accordingly.
It is much nicer in scala however, here it is like it's on the blog:
The code to prepare some coffee would look something like this:
def prepareCappuccino(): Try[Cappuccino] = for {
ground <- Try(grind("arabica beans"))
water <- Try(heatWater(Water(25)))
espresso <- Try(brew(ground, water))
foam <- Try(frothMilk("milk"))
} yield combine(espresso, foam)
where all the methods return a future (typed future), for instance grind would be something like this:
def grind(beans: CoffeeBeans): Future[GroundCoffee] = Future {
// grinding function contents
}
For all the implementations check out the blog but that's all there is to it. You can integrate Scala and Java easily as well. I really recommend doing this sort of thing in Scala instead of Java. Scala requires much less code, much cleaner and event driven.
General programming model for tasks with dependencies is Dataflow. Simplified model where each task has only one, though repeating, dependency is Actor model. There are many actor libraries for Java, but very few for dataflow.
See also: which-actor-model-library-framework-for-java, java-pattern-for-nested-callbacks
Use a BlockingQueue. Put the output of task A into the queue, and task B blocks until something is available in the queue.
The docs contain example code to achieve this: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html
Java defines a class CompletableFuture.
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html
This is what you are looking for.
It helps to build execution flows.
What you need is a CountDownLatch.
final CountDownLatch gate = new CountDownLatch(2);
// thread a
new Thread() {
public void run() {
// process
gate.countDown();
}
}.start();
// thread c
new Thread() {
public void run() {
// process
gate.countDown();
}
}.start();
new Thread() {
public void run() {
try {
gate.await();
// both thread a and thread c have completed
// process thread b
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
As an alternative, depending on your scenario, you might also be able to use a BlockingQueue to implement the Producer-Consumer pattern. See the example on the documentation page.
If task B is dependent on task A's output, I would first question whether or not task B really is a separate task. Separating the tasks would make sense if there is:
Some non-trivial amount of work that task B can do before needing task A's results
Task B is a long ongoing process that handles output from many different instances of task A
There is some other tasks (say D) that also use task A's results
Assuming it is a separate task, then you can allow task A & B to share a BlockingQueue such that task A can pass task B data.
Use this library https://github.com/familysyan/TaskOrchestration. It manages the task dependency for you.
There is a java library specifically for this purpose (Disclaimer : I am the owner of this library) called Dexecutor
Here is how you can achieve the desired result, you can read more about it here
#Test
public void testDependentTaskExecution() {
DefaultDependentTasksExecutor<String, String> executor = newTaskExecutor();
executor.addDependency("A", "B");
executor.addIndependent("C");
executor.execute(ExecutionBehavior.RETRY_ONCE_TERMINATING);
}
private DefaultDependentTasksExecutor<String, String> newTaskExecutor() {
return new DefaultDependentTasksExecutor<String, String>(newExecutor(), new SleepyTaskProvider());
}
private ExecutorService newExecutor() {
return Executors.newFixedThreadPool(ThreadPoolUtil.ioIntesivePoolSize());
}
private static class SleepyTaskProvider implements TaskProvider<String, String> {
public Task<String, String> provid(final String id) {
return new Task<String, String>() {
#Override
public String execute() {
try {
//Perform some task
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
String result = id + "processed";
return result;
}
#Override
public boolean shouldExecute(ExecutionResults<String, String> parentResults) {
ExecutionResult<String, String> firstParentResult = parentResults.getFirst();
//Do some logic with parent result
if ("B".equals(id) && firstParentResult.isSkipped()) {
return false;
}
return true;
}
};
}
}

Categories

Resources