Как смоделировать EntityManager с помощью API макетов jmockit?

У меня проблема с созданием макета EntityManager. Все компилируется, тест запускается, но фиктивный метод возвращает null.

Когда я устанавливаю точку останова внутри издевательского метода «найти», приложение никогда не приостанавливается там. Таким образом мне удалось успешно издеваться над другим классом со статическими методами, но с этим у меня проблемы.

Я использую Jmockit 1.7 вместе с Java 1.8.0. Класс, который я пытаюсь издеваться: javax.persistence.EntityManager

Если нужна еще какая-то информация - спрашивайте. Буду очень благодарен за любую помощь.

Вот мой код:

@RunWith(JMockit.class)
public class ShapefileSerializerTest {

    @Mocked
    private EntityManager em;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        new MockDatabase();
    }

    @Test
    public void testPrepareShapefile() {
        String[][] data = new String[][] {{"1", "100"}, {"1", "101"}, {"1", "102"}, {"1", "103"}, {"2", "200"}, {"2", "201"}};

        List<Map<String, String>> featuresData = Stream.of(data).map(row -> {
            Map<String, String> map = new HashMap<>(2);
            map.put("layerId", row[0]);
            map.put("id", row[1]);
            return map;
        }).collect(Collectors.toList());

        ShapefileSerializer shapefileSerializer = new ShapefileSerializer("shapefiles");
        // if I do not set up the em here - then it will be null inside the tested class
        Deencapsulation.setField(shapefileSerializer, em);

        Response response = shapefileSerializer.prepareShapefile(featuresData);

        assertEquals(Status.OK.getStatusCode(), response.getStatus());
    } 

    public static final class MockDatabase extends MockUp<EntityManager> {
        @Mock
        @SuppressWarnings("unchecked")
        public <T> T find(Class<T> entityClass, Object primaryKey) {
            return (T) new ProjectLayer();
        }
    }
}

person Marcin Roguski    schedule 28.01.2015    source источник


Ответы (1)


Обновите JMockit до версии 1.8 или новее и измените свой тестовый класс на следующий:

@RunWith(JMockit.class)
public class ShapefileSerializerTest {
    @Mocked EntityManager em;

    @Test
    public void testPrepareShapefile() {
        String[][] data = ...
        List<Map<String, String>> featuresData = ...

        ShapefileSerializer shapefileSerializer = new ShapefileSerializer("shapefiles");
        Deencapsulation.setField(shapefileSerializer, em);

        new Expectations() {{
            em.find((Class<?>) any, any); result = new ProjectLayer();
        }};

        Response response = shapefileSerializer.prepareShapefile(featuresData);

        assertEquals(Status.OK.getStatusCode(), response.getStatus());
    } 
}
person Rogério    schedule 28.01.2015
comment
Спасибо за сообщение. К сожалению, это не сработало. Я получаю следующее исключение из блока ожиданий: IllegalArgumentException: Invalid type descriptor: ‹T:Ljava/lang/Object;›(Ljava/lang/Class‹TT›;Ljava/lang/Object;)java/lang/Object; Эта строка вызывает ошибку: result = new ProjectLayer(); Я пробовал это раньше и получил такое же исключение. - person Marcin Roguski; 29.01.2015
comment
@MarcinRoguski Это была ошибка в версии 1.7, исправленная в версии 1.8. Итак, вам нужно обновить JMockit до версии 1.8 или новее. - person Rogério; 29.01.2015
comment
@ Rogério Спасибо, это решило проблему с ожиданиями :) Однако я до сих пор не знаю, почему макетирование EntityManager не сработало. Я также пробовал это с другим классом, и все то же самое. Издевательский метод не вызывается. Даже несмотря на то, что он инстанцируется и передается тестируемому классу с помощью: Deencapsulation.setField(shapefileSerializer, em); - person Marcin Roguski; 30.01.2015
comment
@MarcinRoguski Потому что MockUp не имеют ничего общего с полями @Mocked. Кроме того, при моделировании интерфейса Java (а не класса) вам необходимо вызвать getMockInstance() и использовать возвращенный экземпляр, иначе это не будет иметь никакого эффекта. - person Rogério; 30.01.2015