Is there a way to reuse or reset Vertx in each unit test without having to close it?

533 views
Skip to first unread message

Psycho Punch

unread,
Nov 21, 2016, 8:02:49 AM11/21/16
to vert.x
Base on unit testing documentation (JUnit), during tear down, the Vertx instance needs to be closed. Before each test, it needs to be instantiated. Is there a way to have just one single instance of Vertx and then use it for every test method in the class? When I close the Vertx instance only after all tests have run (e.g. @AfterClass), I get errors involving async being called more than once.

aleks...@googlemail.com

unread,
Nov 22, 2016, 5:47:29 AM11/22/16
to vert.x
Hi Psycho,
this sounds to me, that you are trying to call only one async several times. This will not work. Instead create a new async everytime and close them.

Julien Viet

unread,
Nov 22, 2016, 6:09:06 AM11/22/16
to ve...@googlegroups.com
can you share some code so we understand better what you are doing ?

On Nov 21, 2016, at 2:02 PM, Psycho Punch <rdg...@gmail.com> wrote:

Base on unit testing documentation (JUnit), during tear down, the Vertx instance needs to be closed. Before each test, it needs to be instantiated. Is there a way to have just one single instance of Vertx and then use it for every test method in the class? When I close the Vertx instance only after all tests have run (e.g. @AfterClass), I get errors involving async being called more than once.

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Visit this group at https://groups.google.com/group/vertx.
To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/ca16e70e-619a-4399-b916-6019423084ee%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Psycho Punch

unread,
Nov 22, 2016, 8:27:56 AM11/22/16
to vert.x
Simply put, I have an instance of Vertx in my test that I don't want to (can't) close for each test; it's a singleton instance shared throughout the context of the test.

@RunWith(VertxUnitRunner.class)
public class SampleTest {

   
//shared instance; no @Before, no @After
   
private Vertx vertx;

   
@Test
   
public void testOne(TestContext context) {
       
//invoke async.complete() here
   
}

   
@Test
   
public void testTwo(TestContext context) {
       
//invoke async.complete() here
   
}

}


In the sample code above, depending on the order JUnit runs the tests, the next invocation to async.complete() will fail with the error I described earlier.

Thomas SEGISMONT

unread,
Nov 22, 2016, 9:03:06 AM11/22/16
to ve...@googlegroups.com
Can you please provide a full reproducer as well as the output? Thanks. At least for me there's not enough info here.

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+unsubscribe@googlegroups.com.

Julien Viet

unread,
Nov 22, 2016, 9:56:59 AM11/22/16
to ve...@googlegroups.com
I don’t see the Async here, and I think that’s the important part :-)

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Visit this group at https://groups.google.com/group/vertx.

Psycho Punch

unread,
Nov 22, 2016, 10:16:34 AM11/22/16
to vert.x
Here's a more detailed example:

@RunWith(VertxUnitRunner.class)
public class DemoTest {

   
private static Vertx vertx = Vertx.vertx();


   
@Test
   
public void testOne(TestContext context) {

       
Async async = context.async();
        vertx
.eventBus().consumer("sample", event -> {
            async
.complete();
       
});

        vertx
.eventBus().send("sample", "{}");

        async
.awaitSuccess(TimeUnit.SECONDS.toMillis(1));

   
}

   
@Test
   
public void testTwo(TestContext context) {

       
Async async = context.async();
        vertx
.eventBus().consumer("sample", event -> {
            async
.complete();
       
});

        vertx
.eventBus().send("sample", "{}");

        async
.awaitSuccess(TimeUnit.SECONDS.toMillis(1));
   
}

}


Julien Viet

unread,
Nov 22, 2016, 10:42:49 AM11/22/16
to ve...@googlegroups.com
a couple of comments:

1/ you would need to use different consumer name “sample” like “sample1” or “sample2” - or unregister them

2/ no need for async.awaitSuccess at the end of the test, the runner will wait until async.complete() is called for you

and it should be ok

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Visit this group at https://groups.google.com/group/vertx.

Psycho Punch

unread,
Nov 23, 2016, 11:02:17 AM11/23/16
to vert.x
In the more detailed demo code "sample" is not the name of the consumer but the address that the consumers listen for. However, explicitly unregistering the consumers between tests, solve the problem I was having. Perhaps the reason is that the code I'm testing using the consumers invoke send() instead of publish(). The pitfall was that, in between tests, new consumers are registered to the same event bus under the same Vertx instance. So, I think what I learned from here is that, while it's not necessary to close the Vertx instance in between tests, we should make sure that only the relevant Consumers and Verticles are present for every running test.

As for the async.awaitSuccess, it's necessary for my tests because without it, my test code proceeds to the post-condition checks before the asynchronous Vert.x code is completed. Perhaps if I use TestContext.assert* methods it might work, but I use either JUnit's or AssertJ's assertions most of the time.

Julien Viet

unread,
Nov 24, 2016, 12:07:19 AM11/24/16
to ve...@googlegroups.com
why do you want to keep the same Vertx instance between the tests ?

On Nov 23, 2016, at 5:02 PM, Psycho Punch <rdg...@gmail.com> wrote:

In the more detailed demo code "sample" is not the name of the consumer but the address that the consumers listen for. However, explicitly unregistering the consumers between tests, solve the problem I was having. Perhaps the reason is that the code I'm testing using the consumers invoke send() instead of publish(). The pitfall was that, in between tests, new consumers are registered to the same event bus under the same Vertx instance. So, I think what I learned from here is that, while it's not necessary to close the Vertx instance in between tests, we should make sure that only the relevant Consumers and Verticles are present for every running test.

As for the async.awaitSuccess, it's necessary for my tests because without it, my test code proceeds to the post-condition checks before the asynchronous Vert.x code is completed. Perhaps if I use TestContext.assert* methods it might work, but I use either JUnit's or AssertJ's assertions most of the time.

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Visit this group at https://groups.google.com/group/vertx.

Psycho Punch

unread,
Nov 24, 2016, 11:38:46 AM11/24/16
to vert.x
I'm using Spring in my unit tests, and the Vertx instance is managed in the Spring context.

Jez P

unread,
Nov 24, 2016, 2:10:21 PM11/24/16
to vert.x
Would @DirtiesContext make things too slow? That would make it easier than keeping track of the consumers you add (by forcing a re-creation of the context each time).

Psycho Punch

unread,
Nov 24, 2016, 11:14:03 PM11/24/16
to vert.x
That was actually what I did first. I'm not really sure about the performance differences but I just asked this here so that I know what my options are, just in case.

Jez P

unread,
Nov 25, 2016, 4:42:20 AM11/25/16
to vert.x
I think dirties context throws away the entire context between tests, so the overhead is a reload per test of the context. With large contexts and large numbers of tests you would notice it, but the normal way I used to structure my Spring projects in a build was real unit tests of individual beans outside the context to be run before the "integration tests" which actually loaded contexts, so you'd usually fail pretty fast on the unit tests. 

Psycho Punch

unread,
Nov 25, 2016, 6:42:53 AM11/25/16
to vert.x
I use almost vanilla unit tests where possible (most of the time with domain classes that encapsulate business requirements themselves). However, for more intermediary components like service classes, where I have to wire mocks like repositories, etc. I find it more convenient to use Spring tests. This way, I don't have to define setters, etc. that I don't use for running the actual code anyway. As long as I make sure the configuration classes are self-contained, and the collaborators are just mocks, they work practically much like plain unit tests.

Alexander Lehmann

unread,
Dec 4, 2016, 6:49:51 AM12/4/16
to vert.x
If you are using a "normal" unit test without the vertx runner, you should be able to create a vertx instance at the start of the test and synchronize your test method with CountDownLatch so that it doesn't finish before the async test is finished and then stop the vert.x instance afterwards.

  @Test
 
public void test() throws Exception {
   
Vertx vertx = Vertx.vertx();
   
CountDownLatch latch = new CountDownLatch(1);
    log
.info("timer start");
    vertx
.setTimer(1000, t -> {
      log
.info("timer finished");
      latch
.countDown();
   
});
    latch
.await();
 
}


That should work together with other test runners
Reply all
Reply to author
Forward
0 new messages