【问题标题】:Dependency Injection with QuarkusQuarkus 的依赖注入
【发布时间】:2021-06-16 16:05:51
【问题描述】:

我是 Quarkus 的新手,我正在尝试为名为 DummyReceiver 的对象编写测试。我知道 Quarkus 提供了 @Mock 和其他创建模拟对象的方法,但这有一个缺点,即所有测试中的 每个 实例都将被相同的模拟替换,我不希望这样。所以我尝试做一个简单的依赖注入。

以下是最重要的配置:

<properties>
    <compiler-plugin.version>3.8.1</compiler-plugin.version>
    <maven.compiler.parameters>true</maven.compiler.parameters>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <quarkus-plugin.version>1.13.3.Final</quarkus-plugin.version>
    <quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id>
    <quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
    <quarkus.platform.version>1.13.3.Final</quarkus.platform.version>
    <wiremock.version>2.28.0</wiremock.version>
    <spotless.version>2.11.0</spotless.version>
    <surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
</properties>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-junit5</artifactId>
  <scope>test</scope>
</dependency>

我的代码是这样的:

public interface DummyDependencyInterface {
  void store(String id);
}
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class DummyDependency implements DummyDependencyInterface {

  public void store(String id) {
    System.out.println("DummyDependency stored: " + id);
  }
}
public class DummyMessage {

  private final String scannerInput;

  public DummyMessage(String scannerInput) {
    this.scannerInput = scannerInput;
  }

  public String getScannerInput() {
      return this.scannerInput;
    }
}
import ch.scs.mbv.vega.websocket.ScannerSocketMessage;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;

@ApplicationScoped
public class DummyReceiver {

  private DummyDependencyInterface dependency;

  public DummyReceiver(DummyDependencyInterface dependency) {
    System.out.println("DummyReceiver created with " + dependency.getClass().getName());
    this.dependency = dependency;
  }

  public void onProcessScannerMessage(@Observes DummyMessage message) {
    String scan = message.getScannerInput();
    dependency.store(scan);
  }
}

然后我做这样的测试:

import java.util.concurrent.LinkedBlockingDeque;

public class DummyDependencyMock implements DummyDependencyInterface {

  public LinkedBlockingDeque<String> ids = new LinkedBlockingDeque<>();

  public void store(String id) {
    ids.add(id);
    System.out.println("DummyDependencyMock stored: " + id);
  }
}
import io.quarkus.test.junit.QuarkusTest;
import java.util.concurrent.TimeUnit;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

@QuarkusTest
public class DummyReceiverTest {

  @Inject
  Event<DummyMessage> messageEvent;

  private DummyDependencyMock mock;
  private DummyReceiver receiver;

  @BeforeEach
  public void setup() {
    mock = new DummyDependencyMock();
    receiver = new DummyReceiver(mock);
  }

  @Test
  public void test() throws Exception {
    String id = "123";

    messageEvent.fire(new DummyMessage(id));

    String storedId = mock.ids.poll(1, TimeUnit.SECONDS);
    Assertions.assertEquals("123", storedId);
  }
}

输出显示

DummyReceiver created with scanning.DummyDependencyMock
DummyReceiver created with scanning.DummyDependency_ClientProxy
DummyDependency stored: 123
org.opentest4j.AssertionFailedError: 
Expected :123
Actual   :null

有谁知道出了什么问题以及如何解决?有更好的方法吗?任何建议表示赞赏!

更新:解决方案示例

以下示例用于说明目的,并显示了我能想到的最简单的解决方案。 Example 是我们要测试的类:

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class Example {

  private Delegate delegate;

  Example(Delegate delegate) {
    this.delegate = delegate;
  }

  public void doIt() {
    delegate.execute();
  }
}

我们要模拟的依赖称为Delegate

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class Delegate {

  public void execute() {

  }
}

我们可以编写如下测试来验证Example是否调用了Delegate的方法execute

import static org.mockito.Mockito.verify;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@QuarkusTest
@ExtendWith(MockitoExtension.class)
public class ExampleTest {

  @Mock
  Delegate delegateMock;

  @InjectMocks
  Example example;

  @BeforeEach
  public void setup() {
    MockitoAnnotations.openMocks(this);
  }

  @Test
  public void test() {
    example.doIt();
    verify(delegateMock).execute();
  }
}

【问题讨论】:

    标签: java mockito quarkus


    【解决方案1】:

    您在测试中创建的DummyReceiver 以任何方式不为应用程序的其余部分所知。

    如果你想模拟 DummyDependencyMock,在 Quarkus 中有多种方法可以做到,但 @io.quarkus.test.junit.mockito.InjectMock 是迄今为止最简单的。

    你的代码看起来像

    @QuarkusTest
    public class DummyReceiverTest {
    
      @Inject
      Event<DummyMessage> messageEvent;
    
      @InjectMock
      private DummyDependencyMock mock;
    
    
      @Test
      public void test() throws Exception {
        String id = "123";
    
        messageEvent.fire(new DummyMessage(id));
    
        String storedId = mock.ids.poll(1, TimeUnit.SECONDS);
        Assertions.assertEquals("123", storedId);
      }
    }
    

    请注意,@InjectMock 的使用仅会更改特定测试的模拟 - 有关详细信息,请参阅 this

    【讨论】:

    • 谢谢您的回答!!! This 展示了如何使用 @InjectMockDummyReceiver 替换为模拟。但我不想模拟DummyReceiver,我想注入DummyDependencyMock 而不是DummyDependency。而且我只想在这个测试类中这样做,而不是在所有测试类中。你能告诉我怎么做吗?他们在教程中所做的对我来说似乎毫无意义——为什么要在模拟对象上运行测试?我已经知道它会如何表现,因为它是一个模拟。还是我在这里遗漏了什么?
    【解决方案2】:

    geoand 几乎是正确的,他的回答帮助我弄清楚了其余的 - 谢谢!这是对我有用的代码:

    import io.quarkus.test.junit.QuarkusTest;
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.mockito.MockitoAnnotations;
    import org.mockito.junit.jupiter.MockitoExtension;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    
    @QuarkusTest
    @ExtendWith(MockitoExtension.class)
    public class DummyReceiverTest {
    
      @Inject
      Event<DummyMessage> messageEvent;
    
      @InjectMock
      private DummyDependencyMock mock;
    
      @BeforeEach
      public void setup() {
        MockitoAnnotations.openMocks(this);
      }
    
      @Test
      public void test() throws Exception {
        String id = "123";
    
        messageEvent.fire(new DummyMessage(id));
    
        String storedId = mock.ids.poll(1, TimeUnit.SECONDS);
        Assertions.assertEquals("123", storedId);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-08-22
      • 2020-04-22
      • 1970-01-01
      • 2020-12-04
      • 1970-01-01
      • 2011-04-08
      • 2014-06-12
      相关资源
      最近更新 更多