Вызов API-интерфейса фиктивного отдыха с использованием Robolectric в модульном тесте

Привет, ребята, я использую Robolectric и Mockito и mockito в модульном тестировании, я пришел к выводу, что мне нужно проверить данные, которые зависят от вызова запроса API.

Как вы кодируете, чтобы ваши вызовы Rest API использовали фиктивные данные при запуске модульного теста?

Внутри моего StockFragment.java я использую SpringAndroid + Robospice для выполнения вызова Rest API.
Также у меня есть RequestListener (от Robospice) внутри фрагмента, который обновляет пользовательский интерфейс во фрагменте, если запрос выполнен успешно или нет.

Вот мой фрагмент:

   public class StockFragment extends RoboDialogFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.my_layout, container, false);
        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        displayStockInfo();
    }

    private void displayStockInfo(){
        request = new MyRequest();
        request.setQuote(getStock().getSymbol());
        lastRequestCacheKey = request.createCacheKey();
        ((BaseActivity)getActivity()).getSpiceManager().execute(request, lastRequestCacheKey, DurationInMillis.ALWAYS_EXPIRED, new MyRequestListener());
    }

    private class MyRequestListener implements RequestListener<PseStocksResponse> {
        @Override
        public void onRequestFailure(SpiceException e) {
            //show toast about failure reason ...
        }
        @Override
        public void onRequestSuccess(PseStocksResponse pseStocksResponse) {
            //UPDATE UI VIEWS ...
        }
    }
}

Вот мой класс Robolectric Test.

   public class StockFragmentTest {
    MyRequest request;
    Stock stock;
    StockFragment stockFragment;

    @Before
    public void setUp(){
        stockFragment = new StockFragment();
        FragmentTestUtil.startFragment(stockInfoFragment);
        FragmentTestUtil.startVisibleFragment(stockInfoFragment);
        findViews();
    }

    public void findViews(){
        quoteTextView = (TextView)stockInfoFragment.getView().findViewById(R.id.quoteTextView);
        nameTextView = (TextView)stockInfoFragment.getView().findViewById(R.id.nameTextView );
        ...
    }

    @Test
    public void viewShouldNotBeNull(){
        assertNotNull(quoteTextView);
        assertNotNull(nameTextView);
        ...
    }

    @Test
    public void showDisplayedInfo(){
        //TODO: Assert textview.getText() values here
    }
}

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

Примечание. Robolectric настроен, подтверждено его работоспособность и тестирование. Хотя я не включил их в приведенный выше фрагмент кода. Roboguice также используется в качестве инъекций.


person Hilfritz    schedule 04.02.2015    source источник
comment
Я бы не стал изменять код, чтобы знать о наличии теста   -  person Eugen Martynov    schedule 04.02.2015
comment
Это также не удастся с ClassCastException, так как FragmentTestUtil попытается прикрепить фрагмент к экземпляру Activity, а не BaseActivity   -  person Eugen Martynov    schedule 04.02.2015
comment
Но прежде чем он потерпит неудачу с StubException, потому что вам нужно использовать RobolectricTestRunner   -  person Eugen Martynov    schedule 04.02.2015
comment
Robolectric настроен правильно и не дает сбоев со Stubexception, я просто не включил его в приведенный выше код. Что вы предлагаете для ClassCastException?   -  person Hilfritz    schedule 04.02.2015


Ответы (2)


Я бы посоветовал вам использовать инфраструктуру внедрения зависимостей, например Dagger. На то, чтобы понять, как работает фреймворк, может уйти много времени. Взгляните на примеры.

Я бы также посоветовал вам удалить сетевую логику из представлений. Держите его в Activity.

Также (опционально) я бы скрыл информацию об использовании конкретного сетевого фреймворка - RoboSpice.

На данный момент вы можете исправить тест следующими шагами.

Используйте Robolectric для запуска тестов:

@RunWith( RobolectricTestRunner.class )
@Config( reportSdk = 18, emulateSdk = 18 )
public class StockFragmentTest {...}

Добавить макет для SpiceManager:

...
public class StockFragmentTest 
{
    @Mock
    SpiceManager mockedSpiceManager;

    @Before
    public void setUp()
        throws Exception
    {
        MockitoAnnotations.initMocks( this );
        ...
    }
    ...
}

Создайте тестовую активность:

public class StockFragmentTest 
{
    ...
    public class TestBaseActivity extends BaseActivity 
    {
        @Override
        SpiceManager getSpiceManager() 
        {
            return mockedSpiceManager;
        }
    }
}

Используйте тестовую активность:

@Before
public void setUp()
{
    ...
    stockFragment = new StockFragment();
    FragmentTestUtil.startVisibleFragment( stockFragment, TestBaseActivity.class, <id of placeholder in xml for BaseActivity> );
    ...
}

Я думаю, что последний фрагмент не применим для вашего кода. Вероятно, у вас StockActivity. Таким образом, вы должны сделать TestStockActivity по аналогии и заменить использование BaseTestActivity. Однако я ожидал бы больше побочных эффектов от этого подхода. Правильная инъекция зависимостей поможет

person Eugen Martynov    schedule 04.02.2015
comment
Привет, Евгений, ты прав, ClassCastException происходит. Я использую Roboguice для инъекций. Можете ли вы дать ссылки на ресурсы/статьи, содержащие более подробную информацию или учебные пособия? Понятие все еще слишком широкое для меня. - person Hilfritz; 04.02.2015
comment
Вот как использовать RoboGuice с фрагментами: github.com/roboguice/roboguice /вики/ - person Eugen Martynov; 04.02.2015
comment
Вот как сделать POJO-инъекцию: github.com/roboguice/roboguice/ wiki/Ваша первая POJO-инъекция - person Eugen Martynov; 04.02.2015
comment
Вот как определить привязку: github.com/roboguice/roboguice/wiki /Ваша-первая-индивидуальная-привязка - person Eugen Martynov; 04.02.2015
comment
Вот как переопределить инъекции в тесте: github.com/roboguice/roboguice/blob/master/astroboy/src/test/ - person Eugen Martynov; 04.02.2015
comment
Привет, спасибо Евгений, я обязательно посмотрю на них. - person Hilfritz; 04.02.2015

Robolectric уже содержит поддельный http-уровень, где вы можете подготовить ответы.

Подробности и примеры можно найти в ответах на странице https://stackoverflow.com/questions/18816395/android-http-testing-with-robolectric.

person nenick    schedule 10.02.2015