【发布时间】:2016-09-30 23:45:49
【问题描述】:
我想模拟一个通用接口:
public interface IModel<T, S> {
public S classify(T entity);
}
该接口由 3 个具体类子类化:TextModel、ImageModel、ScoringModel。这些具体类中的每一个都有不同的 T 和 S 参数。
我编写了一个通用方法,它接收具体模型类作为参数并生成模型的模拟版本:
private <T extends IModel<?, ?>> T mockModel(Class<T> modelClass) {
return new MockUp<T>() {
@Mock public Object classify(Object entity) { return null; }
}.getMockInstance();
}
我知道IModel::classify 的输入和输出都有泛型类型,但我还没有找到在模型中使用实际泛型方法的方法。
调用此方法时,我得到一个IllegalArgumentException:
java.lang.IllegalArgumentException:com.classificationmanager.model.$Impl_IModel 类型的值与 com.classificationmanager.model.TextModelFactory#createModel(com.classificationmanager.model.ModelDescriptor) 的返回类型 com.classificationmanager.model.TextModel 不兼容 在 com.classificationmanager.model.ModelFetcherTest$5.(ModelFetcherTest.java:110) 在 com.classificationmanager.model.ModelFetcherTest.mockAllFactories(ModelFetcherTest.java:109) ....... (省去你剩下的)
我认为获取和返回 Object 而不是 T 和 S 是问题所在,但在删除模拟方法并仅模拟类时,我得到了同样的异常:
private <T extends IModel<?, ?>> T mockModel(Class<T> modelClass) {
return new MockUp<T>() {
}.getMockInstance();
}
我可以做一个 switch-case 并返回一个具体的类,但这会很讨厌。
任何涉及 Expectations API 的解决方法也适用于我。
10 倍
【问题讨论】:
-
为什么不使用
@Mocked TextModel? -
我可以,但是我必须模拟 ImageModel、ScoringModel 和 IModel 的所有未来具体子类
-
你不是已经通过调用
mockModel(TextModel.class)来做到这一点,正如问题中所暗示的那样? -
@Rogério 也许我不够清楚。我需要一个根据输入参数 Class 返回 IModel 的具体子类的泛型方法扩展 IModel>。声明一个特定的 Mocked TextModel、Mocked ImageModel 等...不会实现这一点,因为它需要对 IModel 的每个当前和未来子类进行特殊处理(声明)。
标签: java unit-testing generics junit jmockit