我想模拟一个通用接口:

public interface IModel<T, S> {
    public S classify(T entity);
}


该接口分为3个具体类:TextModelImageModelScoringModel。这些具体类中的每一个都有不同的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);
    }
}

07-24 09:28