我有一个带有泛型参数的抽象测试类。
public abstract class AbstractCarTest<G> {
...
@Mock
protected G carMock;
...
}
我已经实现了它的一个具体测试类。
public class TruckTest extends AbstractCarTest<Truck> {
...
when(truckFactory.getTruck(anyString()).return(carMock);
...
}
方法签名如下所示
public Truck getTruck(String name);
当运行TruckTest
时,我得到一个ClassCastException
说
java.lang.ClassCastException: org.mockito.internal.creation.jmock.ClassImposterizer$ClassWithSuperclassToWorkAroundCglibBug$$EnhancerByMockitoWithCGLIB$$... cannot be cast to com.example.Truck
为什么?我有什么办法可以解决这个问题吗?
只是想从@geoand的答案上改进一点。
public abstract class AbstractCarTest<G> {
...
protected G carMock;
...
@Before
public void setUp() throws Exception {
carMock= Mockito.mock(getClazz());
}
private Class<G> getClazz() {
return (Class<G>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
}
public class TruckTest extends AbstractCarTest<Truck> {
...
when(truckFactory.getTruck(anyString()).return(carMock);
...
}
这最终消除了对抽象方法的需求。提供给 getActualTypeArguments() 的
索引将取决于类型参数在声明中的显示位置。在大多数情况下,这将是0
,但是如果你有这样的东西:
public abstract class AbstractCarTest<A, B, C, G>
如果您想使用< code>G的< code>Class,您需要提供< code>3的索引。
Mockito似乎不会在不知道类是具体类型的情况下模拟类。
您可以通过执行以下操作来解决问题:
public abstract class AbstractCarTest<G> {
...
protected G carMock;
...
@Before
public void setUp() throws Exception {
carMock= Mockito.mock(getClazz());
}
protected abstract Class<G> getClazz();
}
public class TruckTest extends AbstractCarTest<Truck> {
...
when(truckFactory.getTruck(anyString()).return(carMock);
...
@Override
protected Class<Truck> getClazz() {
return Truck.class;
}
}
Mockito正在运行时生成您的模拟类。Mocks是通过对给定类进行子类化并覆盖其所有方法来创建的。(因此不嘲笑最终
类或方法的限制。)在运行时,所有泛型类型都被擦除并替换为它们的上限类型,在您的AbstractCarTest
中,这是Object
,因为您没有指定显式上限。因此,Mockito将您的原始类视为:
public abstract class AbstractCarTest {
@Mock
protected Object carMock;
}
在运行时,并将创建一个扩展Object
而不是您想要的Truck
类的mock。(您看不到这一点,因为cglib有一个错误,它无法直接扩展Object
。相反,Mockito正在扩展一个名为ClassSusSuperclass ToWorkAroundCglibBug
的内部类。)通常,编译器会在编译时发出类型错误,其中泛型类型仍然可用,但在运行时,您会遇到堆污染。
解决方法如下:
public abstract class AbstractCarTest<T> {
protected abstract T getCarMock();
// define some base test cases here that use the generic type.
}
public class TruckTest extends AbstractCarTest<Truck> {
@Mock
private Truck carMock;
@Override
protected Truck getCarMock() { return carMock; }
// ...
when(truckFactory.getTruck(anyString()).return(getCarMock());
}
通过在不使用泛型的情况下定义模拟类型,您可以通过getter从抽象基类访问模拟,其中模拟类型被正确定义为Truck
。
我正试图模拟一个泛型方法,但无论我做什么尝试,都会得到类转换异常。正在测试的类是 而测试类是 其他帮助器类和接口有: 此外,出现此错误的原因可能是:1。您使用final/private/equals()/hashCode()方法中的任一个作为存根。这些方法不能被截取/验证。不支持在非公共父类上声明的模拟方法。2.内部when()不是对mock而是对其他对象调用method。
问题内容: 我正在使用Mockito 1.9.5。我有以下代码: 我收到一句编译错误: 但是,当我使用模拟方法时,不会出现错误。谁能告诉我怎么回事?使用该方法时为什么会出现错误?当第三方提供且无法修改时,还有其他方法可以解决此问题吗? 问题答案: 编辑 :从Mockito 1.10.x开始,嵌入在类中的泛型类型现在由Mockito用于深层存根。即。 Mockito尽最大努力获取编译器嵌入的类型信息
我试图模拟Spring Rest的方法。 在同一个测试中,我有多个调用,它们的不同之处在于返回类型。 mock不考虑的泛型参数,最后定义的mock胜过前者。 有什么办法能让它起作用吗?
我正在使用Mockito编写单元测试,但我在模仿注入的类时遇到了问题。问题是两个注入的类是相同的类型,仅通过它们的注释来区分。如果我试图简单地模拟,那么在我的测试中,该模拟不会被注入,并且该对象为。我如何模拟这些对象?
我在我的一个实用程序类中有一个方法,它接受一个集合和一个类对象,并返回一个Iterable实例,该实例可以遍历作为指定类实例的集合的所有成员。其签名为: 这对于大多数用例都非常有效,但现在我需要将其与泛型类