java - 我如何在单元测试中使用 Mockito 或任何 Mocking 框架来模拟 Guice 注入(inject)?

标签 java mockito guice vert.x

我正在尝试编写单元测试用例来使用一些mockito作为模拟框架来测试我的代码,在这之间我遇到了一个问题,我无法模拟我在测试类中使用Google Guice进行的注入(inject)。

我尝试直接注入(inject)对象,它有效,但 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
}

用于测试上述 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();
          });
       });

     } 

}

按照评论之一添加实际代码:

  • 该项目位于 Vert.x 中
    1. 垂直
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()));
  }
}

  • 测试用例
  • 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();
          });
        });
      }
    
    }
    
    

    使用这段代码,不会发生对 DataCreation 的模拟,并且代码流全部通过函数调用进行,我从代码中获得实际结果,而不是模拟的结果。

    最佳答案

    基本上,您有一个在发出请求时创建的注入(inject)器,并且使用该注入(inject)器是因为您使用 requestInjection(this)。这将覆盖您使用的任何类型的注入(inject)。

    具体来说,发生的事情是这样的:

    1. Mockito 注入(inject)模拟。
    2. 您可以使用 injector.injectMembers(this) 覆盖 Mockito 的注入(inject)。

    因此,不要在 start 方法中创建注入(inject)器:根据您使用的各种框架将其移动到适当的位置。

    关于java - 我如何在单元测试中使用 Mockito 或任何 Mocking 框架来模拟 Guice 注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55757232/

    相关文章:

    java - 我怎样才能简化验证一个方法是用某些参数而不是其他参数调用的?

    java - 我可以使用注释让代码在构造函数之前运行吗

    java - 尝试运行 LWJGL "Hello World"时如何解决此 JNI 错误?

    java - PL/SQL : Inserting the values of a column of a table into an array or VARRAY to be accessed by java?

    java - Mockito - 当与 RxJava 2 .retry() 安排时

    java - 无论构造函数签名如何,模拟类的属性

    java - log4j2 修改堆栈跟踪格式

    Java >>>= 运算符

    java - 在java库中使用依赖注入(inject)好不好?

    tomcat - 使用 Guice 记录