Можно ли внедрять макеты для целей тестирования с помощью AndroidAnnotations?

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

@Bean(MyImplementation.class)
MyInterface myInterface;

где класс для ввода уже определен.


person jyoungdev    schedule 05.05.2012    source источник
comment
Вы хотите протестировать свой класс или класс, сгенерированный AndroidAnnotations?   -  person John Ericksen    schedule 14.05.2012
comment
Я хочу протестировать класс, который я пишу. Я хочу внедрить макеты в класс, который я пишу для тестового кода, и внедрить реальные объекты для производства.   -  person jyoungdev    schedule 16.05.2012


Ответы (2)


Вопрос в том, проводите ли вы модульное или интеграционное тестирование?

Если вы проводите модульное тестирование, я бы предложил использовать макеты по старинке, используя сеттер и пытаясь протестировать код Java без участия инфраструктуры внедрения зависимостей. Это проверит ваш класс изолированно и обойдет большую сложность.

Что я имею в виду:

public class Test{

    ClassInTest inTest;
    MyInterface myInterface;

    @Before
    public void setup(){
         inTest = new ClassInTest();
         //or your favorite mocking frameowrk
         myInterface = EasyMock.createMock(MyInterface.class);  
         inTest.setMyInterface(myInterface);
    }

    @Test
    public void testMethod(){
        //...mocking test code
    }
}

Конечно, тестирование действий Android (и других расширений Android) затруднено из-за заглушек и конечных классов/методов, выбрасывающих исключения. Именно здесь Robolectric пригодится (и настоятельно рекомендуется) для создания/затенения Android API.

Если вы проводите интеграционное тестирование, вы можете использовать другой подход. Лично я бы постарался не имитировать во время интеграционных тестов, поскольку я пытаюсь протестировать приложение, как оно будет работать в производственной среде. Но, если вы действительно хотите издеваться, вы можете использовать аналогичный подход к модульному тестированию и ввести макет после того, как вы поднимете свой сгенерированный класс Activity. Стоит отметить, что вы можете выполнять интеграционные тесты непосредственно на оборудовании, используя такие платформы, как Robotium.

Что касается вашего вопроса, мне неизвестны какие-либо средства AndroidAnnotations, специально предназначенные для внедрения Mocks или введения Mocks в внедренное дерево зависимостей приложения.

person John Ericksen    schedule 14.05.2012
comment
Спасибо. Я начал использовать Robolectric для модульных тестов. В примере, который вы привели выше, вы говорите вызвать конструктор моего класса в тестовом методе, чтобы вообще обойти AndroidAnnotations во время тестов? - person jyoungdev; 16.05.2012
comment
Вызов конструктора (с участием Robolectic) просто дает вам экземпляр Activity. Я бы не сказал, что это обходит аннотации Android. Но если вы протестируете свой класс MyActivity (против MyActivity_), то у вас не будет сгенерированного кода, отвечающего за DI из AA. - person John Ericksen; 16.05.2012

Дополнение к ответу johncarl:

  • Невозможно сообщить AndroidAnnotations, что вы хотите внедрить макеты вместо реальных объектов, потому что это работает во время компиляции, поэтому код всегда должен быть готов к работе.

  • Я бы порекомендовал протестировать сгенерированные активности вместе с Robolectric. Аннотации добавляют поведение к вашему коду, поэтому вам не следует тестировать его, как если бы аннотаций не было.

  • Будьте осторожны при тестировании поведения ваших действий, а не поведения AndroidAnnotations. У фреймворка уже есть собственные тесты для проверки правильности работы аннотаций :).

  • Вы можете позволить AndroidAnnotations DI иметь место, а затем повторно внедрить фиктивную зависимость. Поля имеют по крайней мере область действия по умолчанию, что означает, что к ним можно получить доступ из того же пакета, поэтому вам придется создать тест в том же пакете, что и действие.

    MyActivity_ activity = new MyActivity_();
    
    // myInterface gets injected 
    activity.onCreate(null);
    
    // you reinject myInterface
    activity.myInterface = Mockito.mock(MyInterface.class);
    
  • В AndroidAnnotations зависимости вводятся путем вызова MyImplementation_.getInstance_(). Вы можете использовать манипулирование байт-кодом во время выполнения с помощью такого инструмента, как PowerMock, чтобы getInstance_() метод MyImplementation_ возвращал насмешка. Однако для этого может потребоваться некоторая начальная работа, потому что вам придется смешивать средство запуска тестов PowerMock и средство запуска тестов Robolectric.

Изменить: я обновил документацию, добавив контент, основанный на этом вопросе.

person Pierre-Yves Ricau    schedule 19.05.2012
comment
+1. Интересно, что вы предлагаете протестировать сгенерированные действия (пункт 2). Я предполагаю, что в Activity достаточно изменений, чтобы оправдать этот подход. - person John Ericksen; 19.05.2012
comment
@Piwaï Я не уверен, как сработает описанный выше насмешливый подход. Если у вас есть какие-либо методы, аннотированные AfterViews, они будут выполняться как часть создания Activity. Если у этих методов есть какие-либо зависимости, они потерпят неудачу, поскольку у вас еще не было возможности их смоделировать. Любые идеи о том, как обойти это? - person Neil; 17.07.2013
comment
@ Нил, ты нашел какое-нибудь решение для этого? - person Sebastian Roth; 22.10.2014
comment
@SebastianRoth приносит извинения за поздний ответ - я так и не нашел удовлетворительного решения для этого и некоторое время назад отказался от попыток. - person Neil; 27.01.2015
comment
@Piwaï, что мне здесь делать stackoverflow.com/questions/36064047/ - person Kaloyan Roussev; 17.03.2016