How to test async vertx eventbus handlers without sending reply - java

I have two microservices written with java vertx. They communicate via eventbus.
First one sends a message and second receives the message.
First idea: Only reply to Vertx eventbus messages in unit test.
I want to test that message is being processed without errors and therefore I write unit test on second microservice that checks the reply
eventbus.send("address", message, reply -> {
if (reply.succeeded()) {
context.async().complete();
} else {
context.fail();
}});
Now I have to send reply in my consumer, but I want to do it only in test, I do not need to send replies in production. I do not want to consume cpu and network to send replies in production. So what I am looking for is something like this:
vertx.eventBus().consumer("address", handler -> {
Boolean success = methodMayFail();
if ( MY_CONTEXT_IS_TEST || HANDLER_IS_LOCAL_AS_I_ONLY_SENT_LOCAL_MESSAGES_FROM_TEST) {
success ? handler.reply("ok") : handler.fail();
}
});
Second idea came after cdelmas comment and is in my own answer

To test async eventbus handler without reply you have to extract your business logic into service and split your test case into two. First for message passing, second for business logic.
ConsumerVerticle will look like this:
class ConsumerVerticle extends AbstractVerticle {
// this service is injected somehow, for example as constructor parameter
private MyService service;
...
public void start() {
vertx.eventBus().consumer("address", handler -> {
service.methodMayFail();
});
}
}
In async test implement mock of your service with overridden method methodMayFail() that will hold the async
class MockService extends MyService() {
private Async async;
public MockService(Async async) {
this.async = async;
}
#Override public void methodMayFail() {
async.complete()
}
}
And then inject the mock service into verticle
MockService service = new MockService(context.async());
ConsumerVerticle consumerVerticle = new ConsumerVerticle(service);
...
eventbus.send("address", message)
Somewhere in another class MyServiceTest test the implementation of methodMayFail().

It is a very bad practice to add code only for tests.
Although you don't reply, there is probably something you do in the consumer that can be checked, such as updating some state. This is what you should assert in your test, in my opinion.

Related

Call db from async method

I have a Controller that must accept a request and do not wait for the finishing of the processing, give a response.
#PostMapping
#ResponseStatus(HttpStatus.CREATED)
public void processEvent(#RequestBody RequestMyObjectDTO requestMyObjectDTO) {
MyProcessor.process(requestMyObjectDTO);
}
After I give a response, I must execute the processing.
#Async
public void process(RequestMyObjectDTO myRequestObject) {
List<TestObject> testObjects= repository.findAllTestObject();
if (testObjects.isEmpty()) {
return;
}
.............
Is there any difference in where I will go to the database, in the asynchronous method, or outside it? In my case in Controller for example.
How it will impact behavior and what approaches are better?
Given that I need a check:
List<TestObject> testObjects= repository.findAllTestObject();
if (testObjects.isEmpty()) {
return;
}
At the same time, I expect that the controller may receive millions of requests.

How to implement wait in a method call in generic way

I am trying to implement a generic solution for third party API(work in async way) but not getting any idea that how i can implement a call for rest of my application in synchronized way. Basically API is working like take request, process it and then give response when it finish but in meanwhile open to receive other requests as well. So i put API response method in a thread so that monitor continuously either there is a response or not by calling api response method with time interval.
API have interface to take request like:
public void api_execute(string UUID,String request);
API response object:
public APIReponse
{
private String UUID;
private String response_string
// Getter setter
}
I want to write a wrapper on top of this API in which have a single method so that different objects of my application use this to send request and receive response. so UUID will be create by this wrapper class but i am not getting that how i will wait a caller object until i received some response and also distinguish which caller send which request. I was thinking by using observer pattern here but seems to be not fit with this scenario. Can someone give me a hint how i can implement this.
You create async task executor using thread pool
ExecutorService threadpool = Executors.newFixedThreadPool(3);
public Future<APIReponse> submitTask(APIRequest request) throws InterruptedException, ExecutionException {
System.out.println("Submitting Task ...");
Future<APIReponse> future = threadpool.submit(new Callable<APIReponse>() {
#Override
public APIReponse call() throws Exception {
api_execute(request,UUID);
return new APIReponse();
}
});
return future;

Clearing resources on unsubscribe

I am having some trouble with executing some logic when a subscription has been unsubscribed. I've been at this for hours and I have made little progress so far. This is a simplified version of my code:
public class Command<E> {
public CommandActionObservable execute() {
final CommandAction<E> command = createCommand();
final OnSubscribe<CommandAction<E>> onSubscribe = (subscriber) -> {
/* Create a listener that handles notifications and register it.
* The idea here is to push the command downstream so it can be re-executed
*/
final Listener listener = (event) -> {
subscriber.onNext(command);
}
registerListener(listener);
/* This is where I'm having trouble. The unregister method
* should be executed when the subscriber unsubscribed,
* but it never happens
*/
subscriber.add(Subscriptions.create(() -> {
unregisterListener(listener);
}));
// pass the initial command downstream
subscriber.onNext(command);
kickOffBackgroundAction();
}
final Observable<CommandAction<E>> actionObservable = Observable.create(onSubscribe)
.onBackpressureLatest()
.observeOn(Shedulers.io())
.onBackpressureLatest();
return new CommandActionObservable((subscriber) -> {
actionObservable.unsafeSubscribe(subscriber);
})
}
public class CommandActionObservable extends Observable<CommandAction<E> {
// default constructor omitted
public Observable<E> toResult() {
return lift((Operator) (subscriber) -> {
return new Subscriber<CommandAction<E>>() {
// delegate onCompleted and onError to subscriber
public void onNext(CommandAction<E> action) {
// execute the action and pass the result downstream
final E result = action.execute();
subscriber.onNext(result)
}
}
}
}
}
}
I am using the Command in the usual way, adding the resulting subscription to a CompositeSubscription and unsubscribing from it in onDestroy(). Here is an example:
final Observable<SomeType> obs = new Command<SomeType>()
.execute()
.toResult();
subscription.add(obs.subscribe(// impl here));
public void onDestroy() {
super.onDestroy();
subscription.unsubscribe();
}
As mentioned, I can't get the unsubscription logic to work and unregister the listener, which causes memory leaks in the app. If I call doOnUnsubscribe() on obs it gets called, so I am unsubscibing correctly, but maybe the nesting of the observables and lifting causes some issues.
I'd be glad to head opinions on this one.
Turns out it was way easier than I anticipated.
After a bit of digging around I was able to come up with the answer on my own. Just posting this for people that may end up in the same situation as me.
So, as I mentioned in my question, if I added a doOnSubscribe() action to the observable I was getting in my Activity, it gets notified. Next I tried adding the same action on the inner Observables I'm creating in the execute() method. They were not getting called. So, I came to the conclusion that the chain was getting broken somewhere between the observable in my activity and the observables I was creating in execute().
The only thing that was happening to the stream was the application of my custom Operator implemented in toResult(). After a Google search, I came across this excellent article - Pitfalls of Operator Implementation. I was indeed braking the chain in my operator and the upstream observables were not notified of the unsubscription.
After I did what the author advices, all is good. Here is what I needed to do:
lift((Operator) (subscriber) -> {
// connect the upstream and downstream subscribers to keep the chain intact
new Subscriber<CommandAction<E>>(subscriber) {
// the implementation is the same
}
}

How do you call a setup method into a test to stop re-writing the same code

I'm using java and Im trying to call a method into my tests to clean up the code. What is the best way to do this. Will it be to call the method or use the #Before on the setup method I've created. As you will see from the code below there are several repetitions. What will be the best way forward?
import com.pubnub.api.PubnubException;
import org.junit.Before;
import org.junit.Test;
import service.PubnubService;
/**
* Created by peterki on 07/09/2016.
*/
public class PublisherTest {
private PubnubService service = new PubnubService();
#Before
public void setupConnection() throws PubnubException {
// Setup Subscriber
service.subscribe("my_channel");
// Do nothing until the subscriber has connected.
do{} while (!service.isConnected());
}
#Test
public void testPublisher() throws PubnubException {
// Setup Subscriber
service.subscribe("my_channel");
// Do nothing until the subscriber has connected.
do{} while (!service.isConnected());
// Send 10 messages
for(int i = 0; i <= 10; i++){
service.publish("my_channel", "Message: " + i);
}
// Wait until we have recieved the 10 messages
do{}while(service.count() <= 10);
// For each message print out the details
service.getMessages().forEach(System.out::println);
}
#Test
public void testSportMessageType() throws PubnubException {
// Setup Subscriber
service.subscribe("my_channel");
// Wait for Connection
do{} while (!service.isConnected());
// Publish to External Service
//Wait till we receive the message
// Assert the message is what we want
}
}
#Before is called before each #Test. In other words it is a perfect place to do stuff that has to be prepared before the tests run.
I would say that service.subscribe("my_channel"); is perfect to have in #Before.
Instead of #Before you can use #BeforeClass if you want your service to established only once (like a DB connection) otherwise #Before is perfect.
The common code in the test cases can easily be extracted to a method called from each individual test (or - if the same common code is present in all tests - just add them in the #Before)
But your tests will be fragile the way it's currently written. What happens if the service never connects (possibly because a new bug was introduced in the service code)? Your test will hang indefinitely instead of failing.
I would recommend awaitility for that kind of stuff.

Vert.x send NetSocket between Verticles

I am creating a simple TCP server using Vert.x and data is sent between a client and a server in the form of compressed packets.
I would like to use Verticles to create something of this nature (where [Something] is a Verticle and arrows show flow of data):
Buffer In -> [Decompress Packet] -> [Parse Packet] -> Reply to NetSocket
The problem is that I am unsure how I can carry the NetSocket from one Verticle (the result from Decompress Packet) to the next. I can of course send the result from the Decompress Packet to the Parse Packet Verticle but when the Parse Packet Verticle receives this data it will not have any handle to reply to the NetSocket using the reference it has to the sender.
Essentially, I need to carry the NetSocket through the event bus so that once the final Verticle is reached, it can then reply to the data.
As it has been said in the comments you probably want a set of handlers instead of Verticles. Look for example how vertx-web handlers work. A handler is a simple lambda that performs one small task and can decide to pass the work to the next or abort the execution calling a failure method.
A very basic implementation is just to keep a List of lambdas (Java functional interfaces) that you add and once a socket is received you iterate the list.
If you need to perform async IO in your handlers then you cannot use a simple iterator you need to do it async, a basic async iterator wrapper could be:
abstract class AsyncIterator<T> implements Handler<T> {
private final Iterator<T> iterator;
private boolean end = false;
public AsyncIterator(Iterable<T> iterable) {
this(iterable.iterator());
}
public AsyncIterator(Iterator<T> iterator) {
this.iterator = iterator;
next();
}
public final boolean hasNext() {
return !end;
}
public final void next() {
if (iterator.hasNext()) {
handle(iterator.next());
} else {
end = true;
handle(null);
}
}
public final void remove() {
iterator.remove();
}
}
and you just need to use it like:
new AsyncIterator<Object>(keys) {
#Override
public void handle(Object key) {
if (hasNext()) {
// here your handler code...
// once it is complete your handler need to call:
next();
} else {
// no more entries to iterate...
// close your socket?
}
}
};
});
Actually, you don't have to pass netsockets between vertices.
In Vert.x, every socket automatically registers a handler on events, you can use that for your scenario. Check document here:
Every socket automatically registers a handler on the event bus, and when any buffers are received in this handler, it writes them to itself.
This enables you to write data to a socket which is potentially in a completely different verticle or even in a different Vert.x instance by sending the buffer to the address of that handler.
The address of the handler is given by writeHandlerID
Since writeHandlerID is a normal string, it is not a big deal to send it to verticle2 from verticle1. In verticle2, eventbus.send(writeHandlerID, [something you want to reply]). That's it.
We have applied this tip in our Application.

Categories

Resources