java - Mockito 不识别类

标签 java mockito cdi weld-junit5

我尝试使用weld-junit5来模拟一个类。 我 mock 这个类,因为我想知道它被调用的频率。

但是每次我尝试 Mockito.verify() 这个模拟类时,它都会抛出“NotAMockException”

Intellij 调试器正在将该字段验证为:“Mock for MessageService,hashCode:XY”

我已经尝试将我的测试类添加到 WeldInitiator 中,但它不想工作。

“MessageService”是一个真正的类,而不是一个接口(interface)(接口(interface)也不起作用)

Docs

@EnableWeld
class GameServiceTest {

  @WeldSetup
  public WeldInitiator weld = WeldInitiator.from(GameService.class, GameCache.class,
                                                 /** Some More **/,
                                                 GameServiceTest.class).build();
  @Produces
  @ApplicationScoped
  public MessageService createMessageServiceMock() {
    return mock(MessageService.class);
  }

  @Inject
  private MessageService messageService;
  @Inject
  private GameService gameService;

  @Test
  void handleRunningGames() {
    this.gameService.handleRunningGames(null, mock(Session.class));
    // This will throw a org.mockito.exceptions.misusing.NotAMockException
    Mockito.verify(messageService, Mockito.times(1)).writeMessage(any(), any());
  }
}

我希望 Injected MessageService 是一个真正的模拟,我可以在其中调用每个 Mockito 函数,但似乎并非如此。

我有什么问题吗?或者正确的方法是什么?

我想我刚刚解决了这个问题:


  private static final MessageService messageService = mock(MessageService.class);

  @Produces
  @ApplicationScoped
  public MessageService createMessageServiceMock() {
    return messageService;
  }

最佳答案

为了提供一些背景知识,它的工作方式是 Weld 让 Mockito 创建所需的对象,然后将其作为上下文 bean 实例。

但是,在 CDI 中,任何具有正常作用域的 bean 都需要有一个传递的代理而不是该实例。因此,您的生产者实际上所做的(因为它是@ApplicationScoped)是创建对象,将其存储在上下文中,然后创建一个代理并传递该代理。代理是一个不同的对象(没有状态的委托(delegate)),它“知道”如何获取对实际实例的引用。

所以发生的情况是代理被注入(inject)到字段中,并且您正在使用 Mockito.verify() 调用检查代理对象。显然,代理不是模拟本身,因此它失败了。正如用户 @second 所建议的,Weld 提供了一个 API 来解开代理并获取上下文实例。我认为 API 并不“丑陋”,它只是用户不应该主要关心的事情,但有时你无法避免它。

您可以通过使用一些伪作用域(@Dependent 或 CDI @Singleton)来避免使用代理。有了它,它应该可以正常工作,只要它用于测试,用单例替换应用程序范围应该可以工作。

至于你的解决方法,我不知道这如何解决任何问题 - 它基本上是相同的生产者,并且由于范围的原因,它只会被调用一次,因此静态字段不会产生任何影响(因为会有一个单一的调用模拟创建)。除此之外你还改变过其他东西吗?

关于java - Mockito 不识别类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57443438/

相关文章:

java - 我们应该在关闭缓冲流时忽略 IOException 吗?

java - "file:d:\\dir1\file.xml"和 "file:/d:\\dir1\file.xml"作为 FileSystemXmlApplicationContext 参数

java - 如何 stub 我测试类的私有(private)方法调用

CDI:调用哪个实例的@Observes-method?

java - CDI Producer 导致 stackoverflow

java - t :datatable apply css on row

java - 使用 jQAssistant 查找已检查/未检查的异常

java - 如何在实例化时模拟对象?

java - PowerMock、mockito、验证静态方法

jakarta-ee - Glassfish:Weld 不会从一个 jar 中的类注入(inject)到 WEB-INF/lib 中相邻 jar 中的类