Scheduler works incorrect in unit testing - java

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");
}
}

Related

Can we use executor framework and parallel stream together?

I am having List of String to post through Rest api, not sure whether below code is correct performance-wise ??
ExecutorService exService=Executors.newFixedThreadPool(6);
reqList.parallelStream().forEach(reqId->exService.execute(new ReqRunnable(reqId)));
exService.shutdown();
try {
exService.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
}catch(InterruptedException ee) {
LOGGER.warn(String.format("Thread %s has been interuptted %s ",Thread.currentThread().getName(),ee));
// Restore interrupted state...
Thread.currentThread().interrupt();
}
Rest code
public class ReqRunnable implements Runnable {
private static final Logger LOGGER=LoggerFactory.getLogger(ReqRunnable.class);
String reqId;
ReqRunnable(String reqId)
{
this.reqId=reqId;
}
#Override
public void run() {
LOGGER.info(String.format("Thread -%s and reqId - %s",Thread.currentThread().getName(),reqId));
IRSUpdateService.executeRequest(reqId);
}
}

How to write concurrent unit tests

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!")
}
}

How to make JUnit4 "Wait" for asynchronous job to finish before running tests

I am trying to write a test for my android app that communicates with a cloud service.
Theoretically the flow for the test is supposed to be this:
Send request to the server in a worker thread
Wait for the response from the server
Check the response returned by the server
I am trying to use Espresso's IdlingResource class to accomplish that but it is not working as expected. Here's what I have so far
My Test:
#RunWith(AndroidJUnit4.class)
public class CloudManagerTest {
FirebaseOperationIdlingResource mIdlingResource;
#Before
public void setup() {
mIdlingResource = new FirebaseOperationIdlingResource();
Espresso.registerIdlingResources(mIdlingResource);
}
#Test
public void testAsyncOperation() {
Cloud.CLOUD_MANAGER.getDatabase().getCategories(new OperationResult<List<Category>>() {
#Override
public void onResult(boolean success, List<Category> result) {
mIdlingResource.onOperationEnded();
assertTrue(success);
assertNotNull(result);
}
});
mIdlingResource.onOperationStarted();
}
}
The FirebaseOperationIdlingResource
public class FirebaseOperationIdlingResource implements IdlingResource {
private boolean idleNow = true;
private ResourceCallback callback;
#Override
public String getName() {
return String.valueOf(System.currentTimeMillis());
}
public void onOperationStarted() {
idleNow = false;
}
public void onOperationEnded() {
idleNow = true;
if (callback != null) {
callback.onTransitionToIdle();
}
}
#Override
public boolean isIdleNow() {
synchronized (this) {
return idleNow;
}
}
#Override
public void registerIdleTransitionCallback(ResourceCallback callback) {
this.callback = callback;
}}
When used with Espresso's view matchers the test is executed properly, the activity waits and then check the result.
However plain JUNIT4 assert methods are ignored and JUnit is not waiting for my cloud operation to complete.
Is is possible that IdlingResource only work with Espresso methods ? Or am I doing something wrong ?
I use Awaitility for something like that.
It has a very good guide, here is the basic idea:
Wherever you need to wait:
await().until(newUserIsAdded());
elsewhere:
private Callable<Boolean> newUserIsAdded() {
return new Callable<Boolean>() {
public Boolean call() throws Exception {
return userRepository.size() == 1; // The condition that must be fulfilled
}
};
}
I think this example is pretty similar to what you're doing, so save the result of your asynchronous operation to a field, and check it in the call() method.
Junit will not wait for async tasks to complete. You can use CountDownLatch to block the thread, until you receive response from server or timeout.
Countdown latch is a simple yet elegant solution and does NOT need an external library. It also helps you focus on the actual logic to be tested rather than over-engineering the async wait or waiting for a response
void testBackgroundJob() {
Latch latch = new CountDownLatch(1);
//Do your async job
Service.doSomething(new Callback() {
#Override
public void onResponse(){
ACTUAL_RESULT = SUCCESS;
latch.countDown(); // notify the count down latch
// assertEquals(..
}
});
//Wait for api response async
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
assertEquals(expectedResult, ACTUAL_RESULT);
}

How to send periodic messages using WebSocket?

I am using WebSocket on Tomcat (the actual implementation is Tyrus, the reference implementation of JSR 356). It works great, when I have to handle client messages, and respond to them. However, I would like implement a push solution for several of my client-side controls. Actually I need two type of solution:
pushing out data with a specific interval,
pushing out system messages, when they are raised.
For the first one, I think ScheduledExecutorService can be a solution, I already have a more or less working example, I have issues with cleaning up though. For the second one, I think I would need to have a thread, which would trigger a method in the WebSocket endpoint, but I don't really know how to do this cleanly either. And by clean, I mean that I would like to have running threads only if there are connected sessions to my endpoint.
To summarize my question: how would you properly implement a push message solution using the Java EE WebSocket API?
ps.: I would prefer a "pure" solution, but Spring is also not unwelcome.
Current code skeleton
This is how my current solution looks like for the first problem:
#ServerEndpoint(...)
public class MyEndPoint {
// own class, abstracting away session handling
private static SessionHandler sessionHandler = new SessionHandler();
private static ScheduledExecutorService timer =
Executors.newSingleThreadScheduledExecutor();
private static boolean timerStarted = false;
#OnOpen
public void onOpen(Session session, EndpointConfig config) {
sessionHandler.addSession(session);
if (!timerStarted) {
timer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
sessionHandler.sendToAllSession("foo");
}
}, 0, 3, TimeUnit.SECONDS);
timerStarted = true;
}
}
#OnClose
public void onClose(Session session) {
sessionHandler.removeSession(session);
if (0 == sessionHandler.countSessions()) {
// TODO: cleanup thread properly
timer.shutdown();
try {
while (!timer.awaitTermination(10, TimeUnit.SECONDS));
} catch (InterruptedException e) {
log.debug("Timer terminated.");
}
timerStarted = false;
}
}
}
This works more or less, but after a few page reload, it dies with RejectedExecutionException and I am not so sure how to handle the situation.
Unfortunately you can't use any ExecutorService after shutdown();
So after OnClose() method next OnOpen() method will crash.
Just little code for demonstrate:
public class TestThread {
public static void main(String[] args) {
final ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
boolean timerStarted = false;
//OnOpen - 1; - OK
if (!timerStarted) {
timer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
System.out.println("foo");
}
}, 0, 3, TimeUnit.SECONDS);
timerStarted = true;
}
//OnOpen - 2; - OK
if (!timerStarted) {
timer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
System.out.println("foo");
}
}, 0, 3, TimeUnit.SECONDS);
timerStarted = true;
}
//OnClose - 1 - OK
timer.shutdown();
timerStarted = false;
//OnOpen - 2; - NOT OK, because after stop you can't use timer, RejectedExecutionException will thrown
if (!timerStarted) {
// will crash at this invocke
timer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
System.out.println("foo");
}
}, 0, 3, TimeUnit.SECONDS);
timerStarted = true;
}
}
}
You may try to use your class also as a web listener http://docs.oracle.com/javaee/7/api/javax/servlet/annotation/WebListener.html
and create timer in methods that executed on startup and destroy of server
#WebListener
#ServerEndpoint(...)
public class MyEndPoint implements ServletContextListener{
final ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
timer.scheduleWithFixedDelay(...)
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
timer.shutdown();
}
...
}

java.util.concurrent: Transition from Runnable to Executor interface

I am writing a JUnit test case for a DSL, and I need to ensure that the method under test does never end (as in this question).
The provided solution is fine, but I would like to use the "new" Executor interface (Java 5.0 onwards):
#Test
public void methodDoesNotReturnFor5Seconds() throws Exception {
Thread t = new Thread(new Runnable() {
public void run() {
methodUnderTest();
}
});
t.start();
t.join(5000);
assertTrue(t.isAlive());
// possibly do something to shut down methodUnderTest
}
How can I translate the above code from the "old" Thread/Runnable interface to the "new" ExecutorService/Executor interface?
Future<?> future = Executors.newSingleThreadExecutor().submit(new Runnable() {
public void run() {
methodUnderTest();
}
});
try {
future.get(5, TimeUnit.SECONDS);
fail("The task has completed before 5 seconds");
}
catch (TimeoutException e) {
// expected
}

Categories

Resources