【问题标题】:Mockito ClassCastException - A mock cannot be castMockito ClassCastException - 无法投射模拟
【发布时间】:2015-02-11 19:16:30
【问题描述】:

我想测试 AppleProcessor 类中的一个方法:

public void process(Fruit fruit) {
    if(fruit.getType() == Fruit.APPLE) {
        fruitBasket.add(((AppleFruit) fruit).getApple());
    }
    else {
        // do something else
    }
}

请注意,Fruit 是与 AppleFruit 实现的 getType() 方法的接口,并且还具有 getApple() 方法。

我的测试看起来像:

@Mock
FruitBasket fruitBasket;

@Mock
Fruit fruit;

@Mock
AppleFruit apple;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void testAnAppleIsProcessed() {
    AppleProcessor appleProcessor = new AppleProcessoer();
    when(fruit.getType()).thenReturn(Fruit.APPLE);
    when(((AppleFruit) fruit).getApple()).thenReturn(apple);

    appleProcessor.process(fruit);

    verify(fruitBasket).add(isA(Apple.class));
}

但是我收到以下错误:

java.lang.ClassCastException: package.fruit.Fruit$$EnhancerByMockitoWithCGLIB$$b8254f54 cannot be cast to package.fruit.AppleFruit

来自测试中的这一行

when(((AppleFruit) fruit).getApple()).thenReturn(apple);

有人知道如何解决这个问题,以便我可以测试我的代码吗?

【问题讨论】:

    标签: java mocking mockito


    【解决方案1】:

    当你说

    @Mock
    Fruit fruit;
    

    你告诉 Mockito:fruit 变量应该是 Fruit 的一个实例。 Mockito 将动态创建一个实现Fruit 的类(该类为Fruit$$EnhancerByMockitoWithCGLIB$$b8254f54),并创建该类的一个实例。这个类没有理由成为AppleFruit 的实例,因为您没有告诉Mockito 该对象必须是AppleFruit 类型。

    声明为AppleFruit,类型为AppleFruit

    【讨论】:

      【解决方案2】:

      Mockito 可以处理已在模拟时(分配)铸造的模拟对象。但是,它不会在代码执行期间自行转换为模拟对象。

      换句话说(或者更好的是,代码):

      Fruit fruit = Mockito.mock(Applefruit.class);
      

      按照 JB Nizet 所说的去做,你会没事的。我遇到了类似的问题,他的解决方案奏效了。

      这个问题应该是:

      @Mock
      FruitBasket fruitBasket;
      
      @Mock
      AppleFruit fruit; // chaged here
      
      @Mock
      AppleFruit apple;
      
      @Before
      public void setUp() {
          MockitoAnnotations.initMocks(this);
      }
      
      @Test
      public void testAnAppleIsProcessed() {
          AppleProcessor appleProcessor = new AppleProcessoer();
          when(fruit.getType()).thenReturn(Fruit.APPLE);
          when(((AppleFruit) fruit).getApple()).thenReturn(apple);
      
          appleProcessor.process(fruit);
      
          verify(fruitBasket).add(isA(Apple.class));
      }
      

      这就是我们所需要的。

      【讨论】:

        【解决方案3】:

        对于返回超类对象的方法,您可以指示 mockito 返回子类类型的对象。然后你就不需要告诉 mockito 来投射对象了。

        【讨论】:

        • 这方面的一个例子会非常有用...除非您的意思是简单地将其声明为 AppleFruit...
        【解决方案4】:

        对于任何搜索此内容的人,请包括:

        @Mock(extraInterfaces = {AppleFruit.class})
        Fruit fruit;
        

        这将为模拟添加一个额外的接口,并且强制转换不会引发任何异常。

        【讨论】:

          【解决方案5】:

          您的模拟对象由 Mockito 增强,它与您的类不同,因此您不能键入 cast。

          【讨论】:

          • 那么如果不使用模拟对象就没有办法解决它吗?
          • 肯定有。我建议用 appleFruit 实例调用该方法,而不是水果。
          猜你喜欢
          • 2020-07-07
          • 1970-01-01
          • 2019-07-20
          • 1970-01-01
          • 2017-04-24
          • 1970-01-01
          • 1970-01-01
          • 2019-02-22
          • 1970-01-01
          相关资源
          最近更新 更多