Mockito ClassCastException - 无法投射模拟

问题描述 投票:0回答:6

我在类中有一个方法

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
6个回答
51
投票

当你说

@Mock
Fruit fruit;

你告诉 Mockito:

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

将其声明为

AppleFruit
,它将是
AppleFruit
类型。


14
投票

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

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

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


5
投票

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));
}

这就是所需要的。


1
投票

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


0
投票

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


0
投票

@Mock(extraInterfaces) 注释与 PowerMockito 一起使用:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.mockito.Mockito.when;

@RunWith(PowerMockRunner.class)
public class PowerMockitoTest {

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


    @Test
    public void castingMock() {
        when(((Apple) fruit).isRed()).thenReturn(false);
        assert !fruit.isSweet();
    }

}

interface Fruit {

    public boolean isSweet();

}

class Apple implements Fruit {

    @Override
    public boolean isSweet() {
        return isRed();
    }

    public boolean isRed() {
        return true;
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.