我在类中有一个方法
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);
有人知道如何解决这个问题,以便我可以测试我的代码吗?
当你说
@Mock
Fruit fruit;
你告诉 Mockito:
fruit
变量应该是 Fruit
的实例。 Mockito 将动态创建一个实现 Fruit
的类(该类为 Fruit$$EnhancerByMockitoWithCGLIB$$b8254f54
),并创建该类的实例。这个类没有理由成为 AppleFruit
的实例,因为您没有告诉 Mockito 该对象必须是 AppleFruit 类型。
将其声明为
AppleFruit
,它将是 AppleFruit
类型。
对于任何搜索此内容的人,只需包括:
@Mock(extraInterfaces = {AppleFruit.class})
Fruit fruit;
这将为模拟添加一个额外的接口,并且转换不会引发任何异常。
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));
}
这就是所需要的。
对于返回超类对象的方法,您可以指示mockito返回子类类型的对象。然后你就不需要告诉mockito来转换对象了。
你的模拟对象是由 Mockito 增强的,它与你的类不一样,所以你不能类型转换。
@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;
}
}