2016-09-30 2 views
0

Я хочу издеваться общий интерфейс:Невозможно макета общего интерфейса в JMockit

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.TextModel из ком. classificationmanager.model.TextModelFactory # createModel (com.classificationmanager.model.ModelDescriptor) в 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(); 
} 

Я мог бы сделать переключатель -case и вернуть конкретный класс, но это было бы просто противно.

Любое временное решение, связанное с API ожиданий, также будет работать для меня.

10x

+0

Почему бы не использовать '@Mocked TextModel'? –

+0

Я мог бы, но тогда мне придется издеваться над ImageModel, ScoringModel и всеми будущими конкретными подклассами IModel. – KidCrippler

+0

. Разве вы уже этого не делаете, вызывая 'mockModel (TextModel.class)', что подразумевается в вопросе? –

ответ

1

Возможно, следующие примеры могут помочь (хотя я до сих пор не понимаю, вопрос - вероятный случай задачи 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); 
    } 
} 
+0

10x для ответа метод 'Deencapsulation :: newInstance' является хорошим обходным решением для моей проблемы. Во втором тесте, что именно делает аннотация в поле «Захват»? Я не вижу никакого использования входного параметра 'anyModel' в тесте. – KidCrippler

+0

'@ Capturing' расширяет эффект' @ Mocked' для всех классов, реализующих/расширяющих объявленный тип фальшивого поля/параметра (и их экземпляров). –

+0

Да, я знаю это, но в тесте, которое вы указали, не похоже, что экземпляр TextModel совсем издевается, он просто вызывает конкретную реализацию и проверяет, что он фактически возвращает null. Что мне не хватает? – KidCrippler

Смежные вопросы