Best approach for verifying a FutureCallback effect with Jmockit - java

What is the preferred mechanism for verifying the effects of a callback in Jmockit?
For example, assume I have this class.
class ResultGenerator {
AsyncLauncher asyncLauncher = new AsyncLauncher();
public void getResultAsync(final ResultSignal resultSignal) {
asyncLauncher.getResult(new FutureCallback<Result>() {
#Override
public void onSuccess(#Nullable Result result) {
resultSignal.success(result);
}
#Override
public void onFailure(Throwable t) {
resultSignal.failure();
}
});
}
}
How do I verify resultSignal.success(result) when writing a test for ResultGenerator#getResultAsync?

For example
#RunWith(JMockit.class)
public class ResultGeneratorTest {
// Synchronous invocation, mocked AsyncLauncher
#Test
public void testGetResultAsync(#Mocked final ResultSignal resultSignal, #Mocked final Result result) throws Exception {
new MockUp<AsyncLauncher>() {
#Mock
void getResult(FutureCallback<Result> futureCallback) {
futureCallback.onSuccess(result);
}
};
ResultGenerator resultGenerator = new ResultGenerator();
resultGenerator.getResultAsync(resultSignal);
new Verifications() {{
resultSignal.success((Result) any); times = 1;
resultSignal.failure(); times = 0;
}};
}
// Asynchronous invocation, real AsyncLauncher in use
#Test
public void testGetResultAsyncDelayed(#Mocked final Result result) throws Exception {
final AtomicBoolean latch = new AtomicBoolean(false);
MockUp<ResultSignal> resultSignalMockUp = new MockUp<ResultSignal>() {
#Mock(invocations = 1)
public void success(Result result) {
latch.set(true);
}
#Mock(invocations = 0)
public void failure() {
latch.set(true);
}
};
ResultGenerator resultGenerator = new ResultGenerator();
final ResultSignal resultSignal = resultSignalMockUp.getMockInstance();
resultGenerator.getResultAsync(resultSignal);
Awaitility.await().untilTrue(latch);
}
}

Couple of notes:
ResultGenerator is your SUT (System Under Test) and you should not mock internals
ResultSignal is a test collaborator, so it is natural to mock it out
because you can verify the functionality as such, the only "correct" solution from unit testing theory is to mock out the collaborator
You have to be sure that you handle timeout correctly, otherwise the test might never end
so one possible solution is:
#Test
public void getResultAsync_ShouldNotifyResultSignal() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
ResultGenerator generator = new ResultGenerator();
generator.getResultAsync(new MyResultSignal(latch));
assertTrue(latch.await(1, SECONDS));
}
private static final class MyResultSignal implements ResultSignal {
private final CountDownLatch latch;
private MyResultSignal(CountDownLatch latch) {
this.latch = latch;
}
#Override
public void success(Result result) {
latch.countDown();
}
#Override
public void failure() {}
}

Related

Java reactor how to properly start async cancellable sideeffect

I'm trying to write something using reactor which I know how to write using completable futures. I'm getting "Calling subscribe in non-blocking scope" warning in it.
My goal is to call turnOn() with a timeout which should call turnOff() after the timeout. If turnOn() is called again it should cancel the old timeout and wait for a new timeout.
How should I do this? I could do a hibrate and use CompletableFuture for the timeout but reactor's api is just a bit easier.
this test works as expected:
public class TimeoutTest {
Service service;
#BeforeEach
public void setUp() {
service = mock(Service.class);
}
CompletableFuture<Void> turnOffFuture = null;
#DisplayName("Should timeout on turnOn with timeout")
#Test
public void timeoutCompletableFuture() throws InterruptedException {
turnOn(Duration.ofMillis(100)).join();
verify(service).turnOn();
verify(service,never()).turnOff();
Thread.sleep(1000);
verify(service).turnOff();
}
private interface Service{
void turnOn();
void turnOff();
}
public void cancelTimeout() {
if (turnOffFuture != null)
turnOffFuture.cancel(false);
turnOffFuture = null;
}
public CompletableFuture<Void> turnOn(Duration timeout) {
CompletableFuture<Void> turnOnFuture = turnOn();
cancelTimeout();
turnOffFuture = turnOnFuture.thenRun(() -> delay(timeout))
.thenRun(this::turnOff);
return turnOnFuture;
}
private void delay(Duration duration) {
try {
Thread.sleep(BigDecimal.valueOf(duration.getSeconds())
.scaleByPowerOfTen(3)
.add(BigDecimal.valueOf(duration.getNano(), 6))
.intValue());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private CompletableFuture<Void> turnOn() {
return CompletableFuture.runAsync(() -> service.turnOn());
}
private CompletableFuture<Void> turnOff() {
return CompletableFuture.runAsync(() -> service.turnOff());
}
}
but my reactor code does not.
public class TimeoutMonoTest {
Service service;
#BeforeEach
public void setUp() {
service = mock(Service.class);
}
Disposable turnOffDisposable = null;
#DisplayName("Should timeout on turnOn with timeout")
#Test
public void timeoutMono() throws InterruptedException {
turnOn(Duration.ofMillis(100)).block(Duration.ofMillis(10));
verify(service).turnOn();
verify(service, never()).turnOff();
Thread.sleep(1000);
verify(service).turnOff();
}
private interface Service {
void turnOn();
void turnOff();
}
public void cancelTimeout() {
if (turnOffDisposable != null)
turnOffDisposable.dispose();
turnOffDisposable = null;
}
public Mono<Void> turnOn(Duration timeout) {
Mono<Void> turnOnFuture = turnOn();
cancelTimeout();
turnOffDisposable = turnOnFuture.delayElement(timeout)
.subscribe(it -> this.turnOff());
return turnOnFuture;
}
private Mono<Void> turnOn() {
service.turnOn();
return Mono.just("not empty but mapped to void").then();
}
private Mono<Void> turnOff() {
service.turnOff();
return Mono.just("not empty but mapped to void").then();
}
}
The problem lies in the mapping to void mono's in the turnOn() and turnOff() methods. They do not actually get a "next" signal, just a "success" signal.
The fix is simply to change the turnOn method to:
public Mono<Void> turnOn(Duration timeout) {
cancelTimeout();
Mono<Void> turnOnMono = turnOn();
turnOffDisposable = turnOnMono.delayElement(timeout)
.then(turnOff())
.subscribe();
return turnOn();
}

How to unit test asynchronous code made synchronous using CountdownLatch

Below is the class I want to test :
SomeClass.java
public void SomeClass {
final CountDownLatch latch = new CountDownLatch(1);
int result;
registerCallbackWithService(new MyCallback());
public int callToExternalService(){
//Do some stuff and make service call
latch.await();
return result;
}
class MyCallback implements ServiceCallback {
#Override
public void onResult(final int res) {
//do something
result = res;
latch.countdown();
}
}
}
The callback MyCallback was registered earlier before invoking callToExternalService().
If I write a simple test to just mock the service call made in callToExternalService(), the test keeps on running infinitely because of latch.await().
How can I test the logic in callToExternalService() as well as in onResult() ?
I modified by code to expose the callback that I am registering using a package-protected function as below :
public void SomeClass {
private final CountDownLatch latch = new CountDownLatch(1);
private int result;
registerCallback(new MyCallback());
public int callToExternalService(){
//Do some stuff and make service call
latch.await();
return result;
}
private class MyCallback implements ServiceCallback {
#Override
public void onResult(final int res) {
//do something
result = res;
latch.countdown();
}
}
protected registerCallback(ServiceCallback callback) {
registerCallbackWithService(callback);
}
}
Now, for testing I do my testing by creating a new class SomeClassTest extends SomeClass and do my testing using an instance of this class. In SomeClassTest all I do is override registerCallback() to access the callback instance that is being registered.
public class ServiceTest {
private ServiceCallback mServiceCallback;
class SomeClassTest extends SomeClass {
#Override
registerCallback(ServiceCallback callback) {
mServiceCallback = callback;
super.registerCallback(callback);
}
}
}
Now all I have to do it using doAnswer, invoke the callback upon service request which results in the execution of latch.countdown() on the same latch reference that is put on await just after making the service request.
SomeClassTest someClassInstance = new SomeClassTest();
doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
mServiceVCallback.onResult(int_I_want_to_test_for)
return null;
}
}).when(someClassInstance).service_request_before_latch_await();
int response = someClassInstance.callToExternalService();
assertEquals(response, expected_response);

Why doesn't Netty execute my scheduled task?

Using Java 8 and Netty 4.1.1.Final, I would've expected the following test case to succeed, but it times out. What is it that I don't understand w.r.t. nettys event loop and scheduling of tasks?
public class SchedulerTest {
CountDownLatch latch;
TimerHandler handler;
static class TimerHandler extends ChannelInboundHandlerAdapter {
ChannelHandlerContext ctx;
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
this.ctx = ctx;
}
private void timeout(final long ms) {
ctx.executor().schedule(() -> {
ctx.fireUserEventTriggered(ms);
}, ms, TimeUnit.MILLISECONDS);
}
}
static class TimeoutReactor extends ChannelInboundHandlerAdapter {
CountDownLatch latch;
public TimeoutReactor(CountDownLatch latch) {
super();
this.latch = latch;
}
#Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
System.out.println("userEventTriggered");
latch.countDown();
super.userEventTriggered(ctx, evt);
}
}
#Before
public void setUp() throws Exception {
latch = new CountDownLatch(2);
handler = new TimerHandler();
TimeoutReactor reactor = new TimeoutReactor(latch);
new EmbeddedChannel(handler, reactor);
}
#Test(timeout = 1000)
public void test() throws InterruptedException {
handler.timeout(30);
handler.timeout(20);
latch.await();
}
}
Its because EmbeddedChannel is no "real" Channel implementation and mainly use-able for testing and embedded ChannelHandlers. You will need to call "runPendingTasks()" after the given timeframe to have it run. If you use a "real" Channel implementation it will work without any extra method calls.

How to run two classes in parallel using multithreading?

I am working on a project in which I have multiple interface and two Implementations classes which needs to implement these two interfaces.
Suppose my first Interface is -
public Interface interfaceA {
public String abc() throws Exception;
}
And its implementation is -
public class TestA implements interfaceA {
// abc method
}
I am calling it like this -
TestA testA = new TestA();
testA.abc();
Now my second interface is -
public Interface interfaceB {
public String xyz() throws Exception;
}
And its implementation is -
public class TestB implements interfaceB {
// xyz method
}
I am calling it like this -
TestB testB = new TestB();
testB.xyz();
Problem Statement:-
Now my question is - Is there any way, I can execute these two implementation classes in parallel? I don't want to run it in sequential.
Meaning, I want to run TestA and TestB implementation in parallel? Is this possible to do?
Sure it is possible. You have actually many options. Preferred one is using callable and executors.
final ExecutorService executorService = Executors.newFixedThreadPool(2);
final ArrayList<Callable<String>> tasks = Lists.newArrayList(
new Callable<String>()
{
#Override
public String call() throws Exception
{
return testA.abc();
}
},
new Callable<String>()
{
#Override
public String call() throws Exception
{
return testB.xyz();
}
}
);
executorService.invokeAll(tasks);
This method gives you opportunity to get a result from executions of your tasks. InvokeAll returns a list of Future objects.
final List<Future<String>> futures = executorService.invokeAll(tasks);
for (Future<String> future : futures)
{
final String resultOfTask = future.get();
System.out.println(resultOfTask);
}
You can make your code easier to use if you make your classes implements Callable, then you will reduce amount of code needed to prepare list of tasks. Let's use TestB class as an example:
public interface interfaceB {
String xyz() throws Exception;
}
public class TestB implements interfaceB, Callable<String>{
#Override
public String xyz() throws Exception
{
//do something
return "xyz";
}
#Override
public String call() throws Exception
{
return xyz();
}
}
Then you will need just
Lists.newArrayList(new TestB(), new TestA());
instead of
final ArrayList<Callable<String>> tasks = Lists.newArrayList(
new Callable<String>()
{
#Override
public String call() throws Exception
{
return testA.abc();
}
},
new Callable<String>()
{
#Override
public String call() throws Exception
{
return testB.xyz();
}
}
);
Whats more, executors gives you power to maintain and reuse Thread objects which is good from performance and maintainability perspective.
Create Two Thread and run two implementation parallely. Code snippet -
ThreadA{
public void run(){
TestA testA = new TestA();
testA.abc();
}
}
...
ThreadB{
public void run(){
TestB testB = new TestB();
testB.xyz();
}
}
Start this two thread from main method -
public static void main(String[] args){
new ThreadA().start();
new ThreadB().start();
}
Try this one
Collect all the classes of same interface and call them in Multi threading.
Use Callback mechanism to get the result back
import java.util.ArrayList;
import java.util.List;
public class Demo123 {
public static void main(String[] args) {
List<InterfaceA> a = new ArrayList<InterfaceA>();
List<InterfaceB> b = new ArrayList<InterfaceB>();
TestA testA = new TestA();
TestB testB = new TestB();
a.add(testA);
b.add(testB);
for (final InterfaceA i : a) {
new Thread(new Runnable() {
#Override
public void run() {
try {
i.callback(i.abc());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
for (final InterfaceB i : b) {
new Thread(new Runnable() {
#Override
public void run() {
try {
i.callback(i.xyz());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
}
interface MyCallback {
public void callback(String value);
}
interface InterfaceA extends MyCallback {
public String abc() throws Exception;
}
class TestA implements InterfaceA {
#Override
public String abc() throws Exception {
return "abc";
}
#Override
public void callback(String value) {
System.out.println("value returned:" + value);
}
}
interface InterfaceB extends MyCallback {
public String xyz() throws Exception;
}
class TestB implements InterfaceB {
#Override
public String xyz() throws Exception {
return "xyz";
}
#Override
public void callback(String value) {
System.out.println("value returned:" + value);
}
}
You may try it like this:
public static void main(String[] args) throws InterruptedException {
Executors.newCachedThreadPool().invokeAll(Arrays.asList(
new Callable<String>() {
#Override public String call() { return new TestA().abc(); }
},
new Callable<String>() {
#Override public String call() { return new TestB().xyz(); }
}));
}
public interface InterfaceA {
public String abc() throws Exception;
}
public interface InterfaceB {
public String xyz() throws Exception;
}
class TestA implements InterfaceA {
#Override public String abc() {
System.out.println("Inside A"); return null;
}
}
class TestB implements InterfaceB {
#Override public String xyz() {
System.out.println("Inside B"); return null;
}
}

How to set timeout at runtime in JUnit Test Case

I am using JUnit v4 as a test framework. I wanted to know how to set timeout at runtime in Test Case?
I am using Parameterized test. In which I have a list of Scenario, which contains timeout value and some other fileds. Each of these Scenario may have different-2 timeouts.
The timeout parameter is not helping me to achieve this.
#Test(timeout = getTimeOut())
public void secureLoginWithLongUsername() {
// Test case goes here
}
private final long getTimeOut() {
// I am doing some processing here to calculate timeOut dynamically
long timeOut = scenario.getTimeOut();
return timeOut;
}
#Parameters
public static Collection<Scenario[]> getParameters() {
List<Scenario[]> scenarioList = new ArrayList<Scenario[]>();
Configuration config = new Configuration();
List<Scenario> scenarios = config.getScenarios();
for (Scenario scenario : scenarios) {
scenarioList.add(new Scenario[] { scenario });
}
return scenarioList;
}
public class Configuration {
private List<Scenario> scenarios;
//Some processing here
public List<Scenario> getScenarios() {
return scenarios;
}
}
public class Scenario {
private long timeOut;
private String name;
//Some more fields here
}
Please help me to fine out any alternative to set the timeout dynamically.
I think, you need to build it yourself, like:
private Timer timer;
#After
public void terminateTimeout() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
#Test
public void testTimeout() throws Exception {
setTimeout(1000);
// run test...
}
private void setTimeout(int duration) {
final Thread currentThread = Thread.currentThread();
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
currentThread.interrupt();
}
}, duration);
}

Categories