Услуги JUnit Liferay

Я использую liferay service builder в своем проекте, и теперь я хочу проверить классы Util. Это было бы легко, но я не знаю простого метода среды init. Например, при тестировании ant с конфигурацией spring из service.xml(автоматически сгенерировано) я использую InitUtil.initWithSpring() для init beans, но получаю следующую ошибку:

[junit] Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 2,413 sec
[junit] Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 2,413 sec
[junit] 
[junit] Testcase: testJournalArticleSearch(MTest):  Caused an ERROR
[junit] BeanLocator has not been set for servlet context My-portlet
[junit] com.liferay.portal.kernel.bean.BeanLocatorException: BeanLocator has not been set for servlet context My-portlet
[junit]     at com.liferay.portal.kernel.bean.PortletBeanLocatorUtil.locate(PortletBeanLocatorUtil.java:42)
[junit]     at com.my.service.EntityLocalServiceUtil.getService(EntityLocalServiceUtil.java:70)
[junit]     at MTest.setUp(MTest.java:21)

Я видел несколько статей по этой проблеме, но это не работает или я не понимаю эти статьи... Кто-нибудь знает простое решение этой проблемы?

Ответ 1

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

Я часто вижу, что у людей возникают проблемы с написанием модульных тестов для сгенерированного кода - и * Util вместе с servicebuilder звучит как сгенерированный код (* LocalServiceUtil) для меня.

Мой совет - скорее протестировать ваш код * LocalServiceImpl и доверять правильному когенератору (или доверять тому, что тесты кодегенера будут ломать ошибки там, но это вне вашей области). В конце концов, функциональность, предоставляемая классом servicebuilder * LocalServiceUtil, является косвенной, которая ищет правильную реализацию (на основе конфигурации spring) и делегирует ей. В классах LocalServiceUtil нет бизнес-логики - это в классах LocalServiceImpl.

Следующим моментом является то, что иногда даже * Impl-классы трудно тестировать, потому что они обращаются к другим службам, которые нужно будет издеваться. В этом случае - чтобы модульные тесты читались и не зависели от базы данных, я предлагаю протестировать слой кода, который не обращается к другим службам. Чтобы выбрать код, который я украл из этого ответа, вот как бы я лучше его протестировал, исключая UserLocalService из уравнения (осторожность: псевдокод, никогда не видел компилятор, я редактирование в этом поле ввода)

Код, который мы собираемся протестировать:

class MyUserUtil {
  public static boolean isUserFullAge(User user)  {
    Date birthday = user.getBirthday();
    long years = (System.currentTimeMillis() - birthday.getTime()) / ((long)365*24*60*60*1000);
    return years >= 18;
  }
}

Мой тест для этого будет исключать UserLocalService:

@Test
public void testIsUserFullAge() throws Exception {
    //setup (having it here for brevity of the code sample)
    SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd");
    Date D2000_01_01 = format.parse("2000_01_01");
    Date D1990_06_30 = format.parse("1990_06_30");
    User mockUserThatIsFullAge = mock(User.class);
    when(mockUserThatIsFullAge.getBirthday()).thenReturn(D1990_06_30);
    User mockUserThatIsNotFullAge = mock(User.class);
    when(mockUserThatIsNotFullAge.getBirthday()).thenReturn(D2000_01_01);

    //run
    asertTrue(MyUserUtil.isUserFullAge(mockUserThatIsFullAge));
    asertFalse(MyUserUtil.isUserFullAge(mockUserThatIsNotFullAge));
}

Важная часть здесь: ваш код работает с объектом User, а не с идентификатором пользователя. Таким образом, вам не нужно проверять поиск. Если вы отчаянно хотите также проверить поиск (например, тест в более широком масштабе), вызовите его интеграционным тестом. Но не жалуйтесь, если он часто ломается из-за некоторых несвязанных изменений. Потому что теперь причины неудачи теста состоят из двух разных источников: сбой поиска или неправильная реализация. Вы хотите, чтобы ваш UNIT test вышел из строя по одной из причин, например. сразу узнайте, что пошло не так, когда тест завершился неудачно, а не отлаживается.

О, и да, этот тест начнет терпеть неудачу в 2018 году, в реальной жизни я проверил бы больше угловых дел, например. кто-то завтра 18 или вчера сделал это), но это другая тема.

Ответ 2

Я использую Mockito и PowerMock для издевательств над службами Liferay. PowerMock позволяет имитировать статические методы, такие как XXXLocalServiceUtil. В связанном ответе от Prakash K вы можете найти подробное описание: Тестирование для пользовательского портлета подключений: BeanLocatorException и транзакционный откат для тестирования служб