Тестирование для пользовательского плагина портлета: BeanLocatorException и откат транзакции для тестирования сервисов - PullRequest
10 голосов
/ 14 марта 2012

Мои проблемы:

  1. Я могу успешно проверить работу служб CRUD.Я делал вставку в @Before [setUp ()] и удаляю те же данные в @After [tearDown ()], но в будущем мне нужно будет поддерживать транзакции, а не писать код для вставки и удаления.
  2. Я успешно извлекаю отдельные записи своей сущности, но когда я запускаю поисковый запрос или пытаюсь выбрать более одной из моих сущностей, я получаю:

    com.liferay.portal.kernel.bean.BeanLocatorException: BeanLocator не был установлен для контекста сервлета MyCustom-portlet

Я перешел по некоторым из следующих ссылок для настройки Junit с Liferay:

My Enviroment

  • Liferay 6.0.5 EE в комплекте с Tomcat

  • Eclipse Helios с Liferay IDE 1.4 с использованием Junit4

  • Я запускаю свои тесты с помощью команды "ant" в самом затмении, но не набираю Alt + Shift + X , T.

Было бы очень полезно, если бы я мог получить некоторую идею о том, как использовать транзакции с JUnit (или, по крайней мере, некоторые идеи о том, как это работает в liferay)) и как решить BeanLocatorException (или хотя бы зачем его бросать)

Любая помощь будет с благодарностью.

Ответы [ 2 ]

5 голосов
/ 08 августа 2012

Я использую JUnit для тестирования mockito framework и внедряю сервисы через PortalBeanLocatorUtil.setBeanLocator(...) -метод. Я думаю, что это ясно, как сделать это с конфигурацией весны. Здесь у вас есть полный пример, как это можно использовать. Пример снят, и это хорошо, потому что подход прост и понятен.

package mst.unittest.example;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.junit.Before;
import org.junit.Test;

import com.liferay.portal.kernel.bean.BeanLocator;
import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalService;
import com.liferay.portal.service.UserLocalServiceUtil;

import static org.junit.Assert.*;

import static org.mockito.Mockito.*;

/**
 * @author mark.stein.ms@gmail.com
 */
public class MyUserUtilTest {


    private BeanLocator mockBeanLocator;

    @Before
    public void init()  {
        //create mock for BeanLocator, BeanLocator is responsible for loading of Services
        mockBeanLocator = mock(BeanLocator.class);
        //... and insert it in Liferay loading infrastructure (instead of Spring configuration)
        PortalBeanLocatorUtil.setBeanLocator(mockBeanLocator);
    }

    @Test
    public void testIsUserFullAge() throws PortalException, SystemException, ParseException {
        //setup
        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");
        UserLocalService mockUserLocalService = mock(UserLocalService.class);
        User mockUserThatIsFullAge = mock(User.class);
        when(mockUserThatIsFullAge.getBirthday()).thenReturn(D1990_06_30);
        User mockUserThatIsNotFullAge = mock(User.class);
        when(mockUserThatIsNotFullAge.getBirthday()).thenReturn(D2000_01_01);
        //overwrite getUser(...) methode so that wir get mock user-object with mocked behavior
        when(mockUserLocalService.getUser(1234567)).thenReturn(mockUserThatIsFullAge);
        when(mockUserLocalService.getUser(7654321)).thenReturn(mockUserThatIsNotFullAge);

        //load our mock-object instead of default UserLocalService
        when(mockBeanLocator.locate("com.liferay.portal.service.UserLocalService")).thenReturn(mockUserLocalService);


        //run
        User userFullAge = UserLocalServiceUtil.getUser(1234567);
        boolean fullAge = MyUserUtil.isUserFullAge(userFullAge);

        //verify
        assertTrue(fullAge);

        //run
        User userNotFullAge = UserLocalServiceUtil.getUser(7654321);
        boolean notfullAge = MyUserUtil.isUserFullAge(userNotFullAge);

        //verify
        assertFalse(notfullAge);
    }

}

class MyUserUtil {

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

}

Вы можете использовать этот подход также без Mockito Framework, тогда вы должны создать mock-классы, например MockBeanLocator вручную.

Подход с PowerMock

С PowerMock вы можете отказаться от BeanLocator, потому что PowerMock позволяет переопределять статические методы. Вот тот же пример с PowerMock:

package mst.unittest.example;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalServiceUtil;

import static org.junit.Assert.*;

import static org.mockito.Mockito.*;

/**
 * @author Mark Stein
 *
 */

@RunWith(PowerMockRunner.class)
@PrepareForTest(UserLocalServiceUtil.class)
public class LiferayAndPowerMockTest {

    @Test
    public void testIsUserFullAge() throws PortalException, SystemException, ParseException {
        //setup
        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);

        //overwrite getUser(...) by UserLocalServiceUtil  methode so that wir get mock user-object with mocked behavior
        PowerMockito.mockStatic(UserLocalServiceUtil.class);
        when(UserLocalServiceUtil.getUser(1234567)).thenReturn(mockUserThatIsFullAge);
        when(UserLocalServiceUtil.getUser(7654321)).thenReturn(mockUserThatIsNotFullAge);

        //run
        boolean fullAge = MySecUserUtil.isUserFullAge(1234567);

        //verify
        assertTrue(fullAge);

        //run

        boolean notfullAge = MySecUserUtil.isUserFullAge(7654321);

        //verify
        assertFalse(notfullAge);
    }

}

class MySecUserUtil {

    public static boolean isUserFullAge(long userId) throws PortalException, SystemException {
        User user = UserLocalServiceUtil.getUser(userId);
        Date birthday = user.getBirthday();
        long years = (System.currentTimeMillis() - birthday.getTime()) / ((long)365*24*60*60*1000);
        return years > 18;
    }

}

Здесь вы нашли PowerMock 1.4.12 с Mockito и JUnit, включая зависимости http://code.google.com/p/powermock/downloads/detail?name=powermock-mockito-junit-1.4.12.zip&can=2&q=

2 голосов
/ 21 июня 2012

Предположение: вам действительно нужно проверить транзакцию?Или просто бизнес-логика вокруг доступа к БД?Потому что если это так, вы можете попробовать написать модульный тест с EasyMock (или аналогичным), избегая доступа к базе данных, но тестируя функциональность

...