Как смоделировать JSF FacesContext с помощью ViewMap для модульных тестов вне реального веб-приложения?

EDIT: вопрос очищен для удобства чтения. Пожалуйста, игнорируйте комментарии до 31 октября.

В нашем стеке приложений мы работаем со многими меньшими модулями jar, которые объединяются в окончательное веб-приложение. Один модуль определяет функции JSF, такие как реализация этот ВьюСкоп.

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

Важной частью здесь является complete, что означает, что он должен иметь инициализированный ViewMap, поскольку именно здесь наш ViewScope помещает свои объекты.


Я пробовал разные подходы:

1) shale-test: я продвинулся дальше всех, но, к сожалению, проект закрыт.

До сих пор я обернул FacesContext в Provider, что позволяет мне заменить его на Mocked FacesContext для тестирования. Я также изменил сланцевую реализацию AbstractViewControllerTestCase, включив в нее контекст приложения.

Однако при вызове MockedFacesContext.getViewRoot().getViewMap(), так как это вызовет UnsupportedOperationException. Причины, по-видимому, заключаются в том, что MockApplication не создает экземпляр Application.defaultApplication (это значение null), которое требуется для вызова этого метода. Кажется, это ограничение сланцевых испытаний.


2) JMock или mockito Мне кажется, что это не так. действительно издеваются над чем угодно, поскольку большинство членов просто останутся нулевыми. Не знаю, могут ли JMock или mockito вызывать правильные методы инициализации.


3) Custom Faces Mocker: мне кажется, что это единственный оставшийся вариант, но у нас действительно нет времени анализировать, как инициализируется Faces, и воссоздавать поведение для целей имитации. Может быть, кто-то не делал этого раньше и может поделиться основными путевыми точками и ошибками?


Или есть альтернативный способ издеваться над FacesContext вне веб-приложения?


person Pete    schedule 07.09.2011    source источник
comment
Я понятия не имею о части Jmock, но исключение просто пытается сказать вам, что класс javax.el.ELContext отсутствует в текущем пути к классам среды выполнения. Очевидным решением было бы включить его в путь к классам среды выполнения. Настройте путь сборки вашего проекта, чтобы включить библиотеки целевой среды выполнения (servletcontainer/appserver).   -  person BalusC    schedule 07.09.2011
comment
Согласно вашему редактированию, EL API является зависимостью от JSF API. Он использовался для решения этих #{} проблем. EL API обычно уже предоставляется целевой средой выполнения (Tomcat, JBoss, Glassfish и т. д.).   -  person BalusC    schedule 07.09.2011
comment
Ах, мило. Включение зависимости EL помогло. Макетный контекст по-прежнему непригоден для использования, но это один шаг за раз.. может быть, у кого-то все еще есть идеи о том, как использовать jmock с FacesContext или как объединять тестовые классы, которые используют FacesContext.getcurrentinstance(), такие как реализация ViewScope, упомянутая выше. (Кажется, я не смогу обойти FacesContext Wrapper/Provider..? но как лучше всего издеваться над FacesContext?)   -  person Pete    schedule 07.09.2011
comment
Тот факт, что Shale вышел на пенсию, не означает, что вы не можете его получить. Последняя версия находится на Apache Attic и может быть загружена. Я использую его, и он отлично работает, просто издеваясь над FacesContext.   -  person maple_shaft    schedule 07.09.2011
comment
да, я снова попробовал сланец после включения зависимостей EL и получил какой-то контекст лиц. однако он не полностью функционален: вызов getViewRoot().getViewMap() вызовет UnsupportedOperationException Это можно проследить до того, что MockApplication не создает экземпляр частного поля Application.defaultApplication (при вызове ApplicationFactory.getApplication()). Я не знаю, сработало ли это когда-либо, или это просто отсутствие дальнейшего развития.   -  person Pete    schedule 08.09.2011


Ответы (1)


Я бы выбрал PowerMock+Mockito:

Из вашей ссылки:

private Map<String,Object> getViewMap() {
    return FacesContext.getCurrentInstance().getViewRoot().getViewMap();
}

В тесте:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ FacesContext.class });
public class TheTest {
    /*
     * fake viewMap.
     */
    private Map<String,Object> viewMap = Maps.newHashMap() // guava

    /**
     * mock for FaceContext
     */
    @Mock
    private FacesContext faceContext;

    /**
     * mock for UIViewRoot
     */
    @Mock
    private UIViewRoot uiViewRoot;

    @Before
    public void setUp() {
        Mockito.doReturn(this.uiViewRoot).when(this.faceContext).getViewRoot();
        Mockito.doReturn(this.viewMap).when(this.uiViewRoot).getViewMap();

        PowerMock.mockStatic(FacesContext.class);
        PowerMock.doReturn(this.faceContext).when(FacesContext.class, "getCurrentInstance");
    }

    @Test
    public void someTest() {
        /*
         * do your thing and when  
         * FacesContext.getCurrentInstance().getViewRoot().getViewMap(); 
         * is called, this.viewMap is returned.
         */
    }
}

Немного чтения:

person Community    schedule 30.11.2011
comment
Звучит многообещающе. Я попробую это, как только мы вернемся к интерфейсу нашего приложения. Это может занять некоторое время, поэтому, пожалуйста, будьте терпеливы в отношении награды;) - person Pete; 30.11.2011
comment
Точка помогает не получить награду ;o - person ; 30.11.2011