【问题标题】:How to mock injected list of implementations?如何模拟注入的实现列表?
【发布时间】:2021-10-13 01:52:01
【问题描述】:

组件类:

@Slf4j
@Component
@RequiredArgsConstructor
public class Component {

  private final List<MessageHandlerInterface> messageHandlerInterfaces;

  @PostConstruct
  void initInterfaces() {
    mappedInterfaces =
        messageHandlerInterfaces.stream()
            .collect(Collectors.toMap(MessageHandlerInterface::getSubject, Function.identity()));
  }

}

ComponentTest.class:

@SpringJUnitConfig
@SpringBootTest
@ActiveProfiles("test")
class ComponentTest {

  @Autowired private Component component;

  @SpyBean private List<MessageHandlerInterface> interfaces;

  @Test
  public void onMessage() throws ExecutionException, InterruptedException, TimeoutException {
    /*
     * Given
     */
    String testMessage = UUID.randomUUID().toString();
    CompletableFuture<String> completableFuture = new CompletableFuture<>();
    MessageHandlerInterface mockMessageHandlerInterface =
        new MessageHandlerInterface() {
          @Override
          public String getSubject() {
            return SUBJECT;
          }

          @Override
          public void handleMessage(Message message) {
            completableFuture.complete(new String(message.getData()));
          }
        };
    Mockito.when(interfaces.stream()).thenReturn(Stream.of(mockMessageHandlerInterface));
    natsImportDispatcher.initInterfaces();

    /*
     * When
     */
    nc.publish(SUBJECT, testMessage.getBytes());

    /*
     * Then
     */
    Mockito.verify(interfaces, Mockito.times(1)).stream();
    String message = completableFuture.get(2, TimeUnit.SECONDS);
    Assertions.assertEquals(testMessage, message);
  }
}

我想模拟我的MessageHandlerInterface 接口的可用实现。

使用上面的代码我得到一个错误:

org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.List]: Specified class is an interface

我该怎么做呢?

【问题讨论】:

  • 我建议您使用@Mock 注释您的列表并实例化它以包含您的m ockMessageHandlerInterface,然后使用@InjectMocks 注释您的Component 实例。然后您的测试会将您的模拟列表注入实例并使用它。从而无需使用Mockito.when()

标签: java spring junit mockito spring-boot-test


【解决方案1】:

既然您使用的是Mockito,我建议您对您的单元测试进行以下重写:

// Using MockitoJUnitRunner will significantly speed up your unit test as it won't boot up an entire application context
@RunWith(MockitoJUnitRunner.class)
@ActiveProfiles("test")
class ComponentTest {

  // Works like @Autowired but instead injects your @Mock annotated fields
  @InjectMocks private Component component;

  @Mock private List<MessageHandlerInterface> interfaces;

  @Test
  public void onMessage() throws ExecutionException, InterruptedException, TimeoutException {
     /*
      * Given
      */
    String testMessage = UUID.randomUUID().toString();
    CompletableFuture<String> completableFuture = new CompletableFuture<>();

    // Instantiate the list and add the mocked MessageHandlerInterface to it
    interfaces = new ArrayList<>();
    interfaces.add(new MessageHandlerInterface() {
      @Override
      public String getSubject() {
        return SUBJECT;
      }

      @Override
      public void handleMessage(Message message) {
        completableFuture.complete(new String(message.getData()));
      }
    });

    natsImportDispatcher.initInterfaces();

    /*
     * When
     */
    nc.publish(SUBJECT, testMessage.getBytes());

    /*
     * Then
     */
    Mockito.verify(interfaces, Mockito.times(1)).stream();
    String message = completableFuture.get(2, TimeUnit.SECONDS);
    Assertions.assertEquals(testMessage, message);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-02
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2018-01-14
    • 2017-07-07
    相关资源
    最近更新 更多