Mockito ClassCastException - 无法投射模拟

Mockito ClassCastException - A mock cannot be cast

我想测试 class 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);

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

你的模拟对象由 Mockito 增强,它与你的 class 不同,所以你不能类型转换。

当你说

@Mock
Fruit fruit;

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

声明为AppleFruit,类型为AppleFruit

您可以指示 mockito return 子类类型的对象,对于 return 是 super-class 对象的方法。然后你不需要告诉 mockito 来投射对象。

Mockito 可以处理在模拟时间(赋值)时已经投射的模拟对象。但是,它不会在代码执行期间自行转换为模拟对象。

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

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

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

对于这个问题应该是:

@Mock
FruitBasket fruitBasket;

@Mock
AppleFruit fruit; // changed 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));
}

这就是所有需要的。

任何搜索此内容的人只需包括:

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

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