5

I am playing with the Vert.x 3 framework/library. I have written a simple Verticle that has object dependencies managed via Spring IoC.

Here is the Verticle snippet

public class BookmarksVerticle extends AbstractVerticle {
    private static Logger log = LoggerFactory.getLogger(BookmarksVerticle.class);

    @Resource
    private BookmarkDao bookmarksDao;

Here is the Spring configuration snippet

@Bean 
public BookmarkDao bookmarksDao() {
    ...
}
@Bean 
public BookmarksVerticle bookmarkVerticle() {
     return new BookmarksVerticle();
}   

That is all working great. So wanted to write up some tests. I am using the vertx-unit testing and was trying to mock the DAO

Here is what I have

@RunWith(VertxUnitRunner.class)
public class BookmarksVerticleTest {

    int port = 8888;
    private Vertx vertx;

    @Mock(name = "BookmarkDao")
    BookmarkDao mockDao;
    @InjectMocks
    BookmarksVerticle bmVerticle;

    @Before
    public void init(TestContext context) {
        MockitoAnnotations.initMocks(this);

        vertx = Vertx.vertx();
        DeploymentOptions options = new DeploymentOptions().setConfig(new JsonObject().put("http.port", port));
        vertx.deployVerticle(bmVerticle, options, context.asyncAssertSuccess());
    }

However when I run the test I get NPE

SEVERE: NULL
java.lang.NullPointerException
    at vertx.pragprog.bookmarks.BookmarksVerticle.asynchRetrieveBookmark(BookmarksVerticle.java:169)
    at vertx.pragprog.bookmarks.BookmarksVerticle.lambda$1(BookmarksVerticle.java:88)
    at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$14(ContextImpl.java:279)
    at io.vertx.core.impl.OrderedExecutorFactory$OrderedExecutor.lambda$new$161(OrderedExecutorFactory.java:91)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

The line that triggers the exception is where I access the DAO

        Bookmark bm = bookmarksDao.getBookmark(id);

The mockDao is not being injected into the Verticle.

Any ideas on why this might be the case?

UPDATE:

Tried removing the Mockito automatically creating classes by adding a setter method for the DAO on BookmarksVerticle and then changed the setup method in the unit test as follows:

@Before
public void setUp(TestContext context) {    
    log.info("setting up...");
    //MockitoAnnotations.initMocks(this);

    mockDao = mock(BookmarkDao.class);
    bmVerticle = new BookmarksVerticle();
    bmVerticle.setBookmarkDao(mockDao);

    vertx = Vertx.vertx();
    DeploymentOptions options = new DeploymentOptions().setConfig(new JsonObject().put("http.port", port));
    vertx.deployVerticle(bmVerticle, options, context.asyncAssertSuccess());
}

Even with this approach I am still getting NPE

UPDATE 2

I removed vertx and the VertxUnitRunner from the mix by testing a method on BookmarksVerticle that did not have any dependencies on vertx but used the DAO class.

public class BookmarksServiceTest {

    @Mock(name = "BookmarkDao")
    BookmarkDao mockDao;
    @InjectMocks
    BookmarksVerticle bmVerticle;

    @Before
    public void setUp() {   
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test_retrieveBookmark() {
        String id = "1";
        when(mockDao.getBookmark(Matchers.anyString())).thenReturn(new Bookmark(id, "url", "Vert.x"));

        Bookmark bm = bmVerticle.retrieveBookmark(id);
        assertNotNull(bm);
        assertEquals(id, bm.getBookmarkId());
        assertEquals("Vert.x", bm.getBookmarkTitle());
    }

}

This works great! It seems that the VertxUnitRunner may be interfering with Mockito in some way.

Thanks

Mike Barlotta
  • 715
  • 4
  • 16
  • Looks like mockDao is not getting injected into bmVerticle. Try removing the name attribute from @Mock or try @Mock(name = "bookmarksDao") – user2953113 Sep 23 '15 at 22:10
  • Thanks but I tried both of those and that did not work either. I am just not sure why mockDao is not getting injected. I've used it several times before, just not with Vert.x – Mike Barlotta Sep 23 '15 at 22:43
  • On top of that the logging I added (both JUL and log4j) are not working. The latter seems to be b/c it can't find the log4j.xml but that is in the classpath – Mike Barlotta Sep 23 '15 at 22:45
  • Not sure if you need MockitoAnnotations.initMocks(this); when you have @RunWith(VertxUnitRunner.class). – user2953113 Sep 23 '15 at 22:48
  • if I don't call initMocks then what is going to mock the DAO and inject it into the Verticle? – Mike Barlotta Sep 23 '15 at 22:59
  • MockitoJUnitRunner initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks() is not necessary. I'm not sure if this is the case with VertxUnitRunner. – user2953113 Sep 24 '15 at 14:43
  • It seems you are trying to achieve a sort of Unit / Integration test. If you want a Unit Test with mocks, you do not need the "real" Vertx. Try to use *MockitoJUnitRunner.class* instead of *VertxUnitRunner.class* which sounds like an helper for Integration Tests (like the Spring *SpringJUnit4ClassRunner.class* which is often meant to be used for Integration Test). – m c Sep 24 '15 at 15:54
  • The intent was to test the Verticle and make sure that it was listening and processing HTTP requests correctly for Bookmarks and the asynch blocks were coded correctly for success getting data and failures getting data from the DAO. However, I did not want to require a database. – Mike Barlotta Sep 24 '15 at 16:31

2 Answers2

2

Good news is Mockito works with VertxUnitRunner! It turns out using Maven on the command line and from Eclipse was messing me up. Once I switched out the embedded maven to use the same maven install as I was using from the command line things started working.

Here are the details from another answer: Successful build in Maven still showing errors in Eclipse

Community
  • 1
  • 1
Mike Barlotta
  • 715
  • 4
  • 16
1

Does BookmarksVerticle have non-default constructors?

The documentation for @InjectMocks states that field injection will not happen in that case.

See here: http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/InjectMocks.html

sh0rug0ru
  • 1,596
  • 9
  • 9
  • `BookmarksVerticle` only has the default constructor. Thanks. – Mike Barlotta Sep 24 '15 at 16:33
  • When all else fails, get rid of the magic. Try manually creating `BookmarksVerticle` directly with `new`. Leave a protected default constructor for Spring (so that autowiring works) and create a separate public constructor taking `BookmarksDao` so you can pass it directly in for testing. – sh0rug0ru Sep 24 '15 at 16:42
  • I added a setter method for the DAO and eliminating the mock injections as suggested. See the UPDATE in the OP. – Mike Barlotta Sep 24 '15 at 17:00
  • Since you added a setter, here's something to try - move the Spring @Resource annotation from the field to your setter method. If Spring is in the picture, that will cause Spring to use the method instead of reflection to set the `BookmarksDao` value. Then stick your debugger on the setter and see what happens. – sh0rug0ru Sep 24 '15 at 17:02
  • Good idea. However, not sure that will matter since I am not using Spring in the unit test. I did remove Vertx from the mix and it Mockito works as the mockDao is injected (see UPDATE 2). However, as of right now I still can't test the Verticle parts. – Mike Barlotta Sep 24 '15 at 17:16