我想模拟一个通用接口:
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();
}
我可以做一个开关箱并返回一个具体的类,但这太讨厌了。
任何涉及Expectations API的解决方法也都适用于我。
10倍
最佳答案
也许以下示例会有所帮助(尽管我仍然不明白这个问题-XY问题的可能情况)。
public final class ExampleTest {
public interface IModel<T, S> { S classify(T entity); }
static class TextModel implements IModel<Integer, String> {
@Override public String classify(Integer entity) { return "test"; }
}
static class ImageModel implements IModel<String, Image> {
@Override public Image classify(String entity) { return null; }
}
@Test
public void createNonMockedInstanceForAnyModelClass() {
IModel<Integer, String> m1 = mockModel(TextModel.class);
String s = m1.classify(123);
IModel<String, Image> m2 = mockModel(ImageModel.class);
Image img = m2.classify("test");
assertEquals("test", s);
assertNull(img);
}
<T extends IModel<?, ?>> T mockModel(Class<T> modelClass) {
// Or use newUninitializedInstance in case the model class doesn't
// have a no-args constructor.
return Deencapsulation.newInstance(modelClass);
}
@Test
public void mockAllModelImplementationClassesAndInstances(
@Capturing IModel<?, ?> anyModel
) {
IModel<Integer, String> m = new TextModel();
String s = m.classify(123);
assertNull(s);
}
}