How does Mockito timeout work? - java

I'm new to Mockito and JUnit and try to understand basic unit testing with these frameworks. Most concepts in JUnit and Mockito seem straightforward and understandable. However, I got stuck with timeout in Mockito. Does timeout in Mockito play the same role as it does in JUnit? Bellow is my code.
#Mock Timeoutable timeoutable;
#Test(timeout = 100)
public void testJUnitTimeout() {
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
}
}
#Test
public void testMockitoTimeout(){
doAnswer(new Answer() {
#Override public Object answer(InvocationOnMock invocation){
try {
Thread.sleep(1000);
} catch (InterruptedException ie){
}
return null;
}
}).when(timeoutable).longOperation();
timeoutable.longOperation();
verify(timeoutable, timeout(100)).longOperation();
}
I expected that both tests failed. But only testJUnitTimeout() failed. Why does the second test pass?
Thank you very much.

Verification with timeout is intended to be used to verify whether or not the operation has been invoked concurrently within the specified timeout.
It provides a limited form of verification for concurrent operations.
The following examples demonstrate the behaviour:
private final Runnable asyncOperation = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
timeoutable.longOperation();
} catch (InterruptedException e) {
}
}
};
#Test
public void testMockitoConcurrentTimeoutSucceeds(){
new Thread(asyncOperation).start();
verify(timeoutable, timeout(2000)).longOperation();
}
#Test
public void testMockitoConcurrentTimeoutFails(){
new Thread(asyncOperation).start();
verify(timeoutable, timeout(100)).longOperation();
}

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.

AutoCloseable-ish method but runs only on catch

I would like to two have two different methods running in catch and final blocks. I have found AutoCloseable interface, but I need something to fire in case of exception only.
Like:
SomeService service = CreateService().andOpenTransaction()
try {
service.doSomeMessyThingsInsideDB();
} catch (Exception e) {
service.rollbackTransaction();
throw e;
} finally {
service.closeConnection();
}
Is there any way to make it simpler? As I said I am familiar with AutoCloseable, but it helps me only with finally block. I still cannot use it inside the catch.
Well you could define your own interface, and then some static runner method:
public interface ErrorHandlingCloseable extends AutoCloseable {
void run() throws Exception;
void onError(Exception e);
static void execute(ErrorHandlingClosable ehc) throws Exception {
try(ErrorHandlingClosable temp = ehc) {
ehc.run();
} catch(Exception e) {
ehc.onError(e);
throw e;
}
}
}
Which you then could then call like this:
SomeService service = CreateService().andOpenTransaction();
ErrorHandlingCloseable.execute(new ErrorHandlingCloseable() {
public void run() throws Exception { service.doSomeMessyThingsInsideDB(); }
public void onError(Exception e) { service.rollbackTransaction(); }
public void close() throws Exception { service.closeConnection(); }
});
But you see, it's still messy.
You could even implement this interface in your SomeService but then you're restricted that the run() method will always call doSomeMessyThingsInsideDB().
Another way but still similar would be to use Java8 and create a helper functional interface:
public interface ThrowingRunnable {
void run() throws Exception;
}
And then a static method somewhere:
public static void execute(ThrowingRunnable action,
ThrowingRunnable onCatch,
ThrowingRunnable onFinally) throws Exception {
try(AutoCloseable ao = onFinally) {
action.run();
} catch(Exception e) {
onCatch.run();
throw e;
}
}
The interesting part is probably this: try(AutoCloseable ao = onFinally), which "registers" your onFinally method to be called when finally is reached.
This could then be called like this:
execute(
service::doSomeMessyThingsInsideDB,
service::rollbackTransaction,
service::closeConnection
);
You said you are familiar with AutoCloseable, but you don't use it.
Have you considered using try-with-resources statement?
Your code can be simplified to:
try (SomeService service = CreateService().andOpenTransaction()) {
service.doSomeMessyThingsInsideDB();
} catch(exception e){
service.rollbackTransaction();
throw e;
}
Oracle has great doc for that, including examples.
Note: A try-with-resources statement can have catch and finally blocks just like an ordinary try statement. In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed.
Answering your question, this is as simple as it can get.
If your class doesn't implement Closeable then you can either implement it or use finally.
First step: Handling the exception
You evidently want the exception handled before some close. Then you need inside a try-with-resources to handle the exception.
/** throws RuntimeException */
void process(Callable<Void> work, Consumer<Exception> onFail) {
try {
work.call();
} catch (Exception e) {
onFail(e);
}
}
try (SomeService service = CreateService().andOpenTransaction()) {
process(() -> service.doSomeMessyThingsInsideDB(),
e -> {
service.rollbackTransaction();
throw new IllegalStateException(e);
});
}
This is not very satisfactory, but again also integrating the AutoCloseable, might give too few use-cases.
Second step: with AutoCloseable
<SV extends AutoCloseable> void processAutoClosing(Supplier<SV> serviceFactory,
Callable<Void> work, Consumer<Exception> onFail) {
try (SV service = serviceFactory.get()) {
process(work, onFail);
}
}
processAutoClosing(...);

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

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

JUnit service class with executors return control immediately

I have next service class:
public class JDBCServiceImpl {
//////
public void writeTablesColumnsToFiles(DataSource dataSource, List<Table> tableInfos) {
ExecutorService executor = Executors.newFixedThreadPool(2);
for (Table table : tableInfos) {
Runnable worker = new Runnable() {
#Override
public void run() {
try {
writeTableColumnsToFiles(dataSource, table);
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
executor.execute(worker);
}
executor.shutdown();
}
//////
public void writeTableColumnsToFiles(DataSource dataSource, Table tableInfo) {
//
try (Connection connection = dataSource.getConnection()) {
.....
}
}
}
I would like to test this service in JUnit class:
public class JDBCLoaderServiceImpl {
#Test
public void testExecutingOfJDBCService() {
.....
JDBCServiceImpl jdbcLoaderService = new JDBCServiceImpl();
jdbcLoaderService.writeTablesColumnsToFiles(dataSource, allTables);
}
}
The main problem that JUnit doesn't wait while executor complete it task (in debug mode I see that after this code try (Connection connection = dataSource.getConnection()) service class return control). So how to fix this issue? Thanks in advance.
I suggest to test writeTableColumnsToFiles(DataSource dataSource, Table tableInfo) and ignore method that work with threads.
But if you really want to test it you can mock ExecutorService and do all work in single thread.
In general, JUnit isn't for testing multi-threaded execution. (It's for unit testing... right there in the name.)
For instance, if one or even all of your worker threads were to throw exceptions and die, your JUnit test harness --- running in a completely different thread --- wouldn't notice. Unless your test specifically asserted that no such failure had occurred, JUnit would record it as having passed, since the test itself hadn't thrown or propagated any exceptions.
Okay I add next code to writeTablesColumnsToFiles method:
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
This solve my issue.

Categories

Resources