1

I am trying to write unit test case to test my code with some mockito as mocking framework, In between i came across a problem where in i am unable to mock injection that i made using Google Guice in my test class.

I tried Directly injecting the object , It works but no luck with Google Injection.

class SomeClassToCreateWiskey{
// Some Service
@Inject
@Named("dataCreation")
DataCreation dataCreation;

public apis(){
    Injector injector = Guice.createInjector(new DataCreationModel());
    injector.injectMembers(this);
    int port = config().getInteger("http.port", 8080);
    Router router = Router.router(vertx);
    router.route("/api/getAll").handler(this::getAll);
  }
// getAll method will return some json result
}

Test Class to test above API

class SomeClassToCreateWiskeyTest{
     @Mock
     private DataCreation dataCreation;
     // setting up before and after config
     @Before
     MockitoAnnotations.initMocks(this);
       ......
     @After
       ......
     @Test
     public void testGetAll(){
       Map<Integer, Whisky> dataSets = new LinkedHashMap<>();
       Whisky w1 = new Whisky("Bowmore 15 Years Laimrig", "Scotland, Islay");
       Whisky w2 = new Whisky("Talisker 57° kya h", "Scotland, Island");
      Async async = context.async();
      dataSets.put(w1.getId(), w1);
      dataSets.put(w2.getId(), w2);
      when(dataCreationDao.getData()).thenReturn(dataSets);
      when(dataCreation.getData()).thenReturn(dataSets);
      HttpClient client = vertx.createHttpClient();
      client.getNow(port, "localhost", "/api/getAll", response -> {
      response.bodyHandler(body -> {
        System.out.println(body.toString());
        client.close();
        async.complete();
          });
       });

     } 

}

Adding the actual code as asked in one of the comment :

  • The project is in Vert.x
    1. Verticle
package com.testproject.starter.verticles;

import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.testproject.starter.model.DataCreationModel;
import com.testproject.starter.services.DataCreation;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.json.Json;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;

public class ErrorReproduction extends AbstractVerticle {
  @Inject
  @Named("dataCreation")
  DataCreation dataCreation;

  //DataCreation dataCreation = new DataCreationImpl();
  @Override
  public void start(Future<Void> startFuture) throws Exception {
    Injector injector = Guice.createInjector(new DataCreationModel());
    injector.injectMembers(this);
    int port = config().getInteger("http.port", 8080);
    Router router = Router.router(vertx);
    router.route("/api/getAll").handler(this::getAll);
    vertx.createHttpServer().requestHandler(router::accept)
      .listen(port,result -> startFuture.complete());
  }
  public void getAll(RoutingContext routingContext) {
    routingContext.response().putHeader("content-type", "application/json")
      .end(Json.encodePrettily(dataCreation.getData().values()));
  }
}

  1. Test Case
package com.testproject.starter.verticles;

import com.testproject.starter.dao.DataCreationDao;
import com.testproject.starter.ppojo.Whisky;
import com.testproject.starter.services.DataCreation;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClient;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.RunTestOnContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

import java.io.IOException;
import java.net.ServerSocket;
import java.util.LinkedHashMap;
import java.util.Map;

import static org.mockito.Mockito.when;

@RunWith(VertxUnitRunner.class)
public class ErrorReproductionTest {
  Vertx vertx;
  int port;
  @Mock
  private DataCreation dataCreation;
  @Mock
  private DataCreationDao dataCreationDao;
  @Rule
  public RunTestOnContext rule = new RunTestOnContext();

  @Rule
  public MockitoRule mockitoRule = MockitoJUnit.rule();
  @InjectMocks
  private ErrorReproduction errVertical;

  @Before
  public void before(TestContext context) throws IOException {
    MockitoAnnotations.initMocks(this);
    ServerSocket socket = new ServerSocket(0);
    port = socket.getLocalPort();
    socket.close();
    DeploymentOptions options = new DeploymentOptions()
      .setConfig(new JsonObject().put("http.port", port));
    vertx = Vertx.vertx();
    rule.vertx().deployVerticle(errVertical, options, context.asyncAssertSuccess());
  }
  @After
  public void after(TestContext context) {
    vertx.close(context.asyncAssertSuccess());
  }
  @Test
  public void testGetAll(TestContext context){
    Map<Integer, Whisky> dataSets = new LinkedHashMap<>();
    Whisky w1 = new Whisky("Bowmore 15 Years Laimrig", "Scotland, Islay");
    Whisky w2 = new Whisky("Talisker 57° kya h", "Scotland, Island");
    Async async = context.async();
    dataSets.put(w1.getId(), w1);
    dataSets.put(w2.getId(), w2);
    when(dataCreationDao.getData()).thenReturn(dataSets);
    when(dataCreation.getData()).thenReturn(dataSets);
    HttpClient client = vertx.createHttpClient();
    client.getNow(port, "localhost", "/api/getAll", response -> {
      response.bodyHandler(body -> {
        System.out.println(body.toString());
        client.close();
        async.complete();
      });
    });
  }

}

With this piece of code the mocking of DataCreation is not happening and the code flow is going all trough the function call and i am getting the actual result from my code not the mocked one.

Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
Ashutosh
  • 917
  • 10
  • 19
  • None of the code you posted would compile. Post a complete, valid, minimal example reproducing the issue. – JB Nizet Apr 19 '19 at 06:28
  • Does that really needed ?, I guess i am sure that i m making sense with my question. Still if you want me to post that i can do that but its all together a project and its gonna be bit lengthy :) – Ashutosh Apr 19 '19 at 07:03
  • We don't need your actual, lengthy code. We need a complete minimal example reproducing the problem. There are so many issues in the code you posted that we can't know which of them are intentional to reduce the code and which of them are actual mistakes. – JB Nizet Apr 19 '19 at 07:22
  • Sure, I will post a minimal code reproducing the issue. Thanks much for the suggestion. – Ashutosh Apr 19 '19 at 07:42
  • ++ Added the code , Please check now – Ashutosh Apr 19 '19 at 11:01
  • This seems to be a Vert.x problem more than a Mockito/Guice problem, and I don't know anything about Vert.x. I've added the vert.x tag to the question. – JB Nizet Apr 19 '19 at 11:08
  • Thanks but what ever i have researched it sounds me to Mockito - Guice problem. If i will remove Guice injection and add the following line it works as expected : //DataCreation dataCreation = new DataCreationImpl(); – Ashutosh Apr 19 '19 at 11:18

1 Answers1

2

Basically, you have an injector that is created when you do a request, and that injector is used because you use requestInjection(this). That will override any kind of injection you use.

Concretely, here's what's happening:

  1. Mockito injects the mocks.
  2. You override Mockito's injections with injector.injectMembers(this).

So do not create an injector in the start method: move it where appropriate, depending on the various frameworks you use.

Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
  • Thank you for the answer , I am using vert.x and i feel like that is the place where i need the injection. – Ashutosh Apr 21 '19 at 17:30
  • @AshutoshKumar well, it's evidently not. I explain the consequences of doing it like that. So you have to find another place. – Olivier Grégoire Apr 21 '19 at 17:38
  • i guess i can make it happen in other place as well , Let me try if it works. I will be back with that exercise. – Ashutosh Apr 22 '19 at 11:53