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;
这将为模拟添加一个额外的接口并且转换不会引发任何异常。
我想测试 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;
这将为模拟添加一个额外的接口并且转换不会引发任何异常。