1

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

Как вы кодируете, чтобы ваши вызовы 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 также используется в качестве инъекций.

+1

Я хотел бы избежать модификации кода, чтобы знать о присутствии тестируемого –

+1

Это также потерпит неудачу с '' ClassCastException' так FragmentTestUtil' попытается присоединить фрагмент к экземпляру ' Activity' not 'BaseActivity' –

+0

Но прежде чем он сработает с' StubException', потому что вам нужно использовать 'RobolectricTestRunner' –

ответ

0

Я бы посоветовал вам использовать рамки для инъекций зависимостей, такие как 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. Однако я ожидал бы большего количества побочных эффектов от этого подхода.Правильная инъекция зависимости поможет

+0

Привет, Евгений, вы правы, когда происходит ClassCastException. Я использую Roboguice для инъекций. Можете ли вы дать ссылки на ресурсы/статьи, содержащие более подробную информацию или учебники? Эта концепция по-прежнему слишком широка для меня. – Hilfritz

+0

Вот как использовать RoboGuice с фрагментами: https://github.com/roboguice/roboguice/wiki/Your-First-Injected-Fragment –

+0

Вот как сделать POJO-инъекцию: https://github.com/ roboguice/roboguice/wiki/Your-First-POJO-Injection –