Насмешка EntityManager

Я получаю NPE, издеваясь над EntityManager, ниже мой код,

@Stateless
public class NodeChangeDeltaQueryBean implements NodeChangeDeltaQueryLocal {

    @PersistenceContext
    private EntityManager em;
    @Override
    public String findIdByNaturalKey(final String replicationDomain, final int sourceNodeIndex,
                                     final int nodeChangeNumber) {
        List<String> result =
            NodeChangeDelta.findIdByNaturalKey(this.em, replicationDomain, sourceNodeIndex,
                nodeChangeNumber).getResultList();
        return result.isEmpty() ? null : result.get(0);
    }
}

Мой класс сущности

@Entity
public class NodeChangeDelta implements Serializable, Cloneable, GeneratedEntity, KeyedEntity<String> {

public static TypedQuery<String> findIdByNaturalKey(final EntityManager em, final String replicationDomain, final int sourceNodeIndex, final int nodeChangeNumber) {
        return em.createNamedQuery("NodeChangeDelta.findIdByNaturalKey", String.class)
            .setParameter("replicationDomain", replicationDomain)
            .setParameter("sourceNodeIndex", sourceNodeIndex)
            .setParameter("nodeChangeNumber", nodeChangeNumber);
    }
}

Мой тестовый класс

@RunWith(MockitoJUnitRunner.class)
public class NodeChangeDeltaQueryBeanTest {

    @InjectMocks
    NodeChangeDeltaQueryBean nodeChangeDeltaQueryBean;

    @Mock
    EntityManager em;

@Test
    public void testFindIdByNaturalKey() {
        this.addNodeChangeDelta();
        this.nodeChangeDeltaQueryBean.findIdByNaturalKey(this.REPLICATION_DOMAIN,
            this.SOURCE_NODE_INDEX, this.NODE_CHANGE_NUMDER);
    }
}

При отладке em не равен нулю (также другие аргументы REPLICATION_DOMAIN, SOURCE_NODE_INDEX, NODE_CHANGE_NUMDER не равны нулю) в классе Entity, тогда как em.createNamedQuery("NodeChangeDelta.findIdByNaturalKey", String.class) равен нулю.


person Arasu    schedule 06.04.2015    source источник
comment
Ожидаете ли вы, что ваш макет выполнит фактический запрос? Это не сработает. Он ничего не знает о вашем источнике данных, контексте персистентности, именованных запросах и т. д.   -  person Robby Cornelissen    schedule 06.04.2015


Ответы (2)


В вики mockito: Не имитируйте типы, которыми вы не владеете!

Это не жесткая линия, но ее пересечение может иметь последствия! (скорее всего, так и будет.)

  1. Представьте себе код, который издевается над сторонней библиотекой. После определенного обновления третьей библиотеки логика может немного измениться, но набор тестов будет выполняться нормально, потому что он смоделирован. Итак, позже, думая, что все в порядке, стена сборки в конце концов зеленая, программное обеспечение развернуто и... Бум
  2. Это может быть признаком того, что текущий дизайн недостаточно отделен от этой сторонней библиотеки.
  3. Еще одна проблема заключается в том, что сторонняя библиотека может быть сложной и требовать много макетов даже для правильной работы. Это приводит к чрезмерно определенным тестам и сложным фикстурам, что само по себе ставит под угрозу цель компактности и удобочитаемости. Или к тестам, которые недостаточно охватывают код из-за сложности имитации внешней системы.

Вместо этого наиболее распространенным способом является создание оболочек вокруг внешней библиотеки/системы, хотя следует помнить о риске утечки абстракции, когда слишком много низкоуровневых API, концепций или исключений выходит за границы оболочки. Чтобы проверить интеграцию со сторонней библиотекой, напишите интеграционные тесты, а также сделайте их максимально компактными и читабельными.

Поддельный тип, которым вы не управляете, может считаться (насмешливым) анти-шаблоном. Хотя EntityManager в значительной степени является стандартным, не следует думать, что в будущих выпусках JDK/JSR не будет каких-либо изменений в поведении (это уже случалось много раз в других частях API, просто взгляните на JDK примечания к выпуску). Кроме того, реальные реализации могут иметь тонкости в своем поведении, которые вряд ли можно высмеять, тесты могут быть зелеными, но производственные коты горят (правдивая история).

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

Также вики ссылается на другие записи в блогах, описывающие проблемы, с которыми они столкнулись, когда пытались имитировать тип, который они не могли контролировать.

Вместо этого я действительно советую всем не использовать mock при тестировании интеграции с другой системой. Я считаю, что для работы с базами данных Arquillian - это то, что нужно, проект, похоже, довольно активен.


Адаптировано из моего ответа: https://stackoverflow.com/a/28698223/48136

person Brice    schedule 06.04.2015