Извикване на API за фалшива почивка с помощта на Robolectric в Unit test

Здравейте момчета, използвам 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 /wiki/ - person Eugen Martynov; 04.02.2015
comment
Ето как да направите POJO инжектиране: github.com/roboguice/roboguice/ wiki/Your-First-POJO-Injection - person Eugen Martynov; 04.02.2015
comment
Ето как да дефинирате обвързването: github.com/roboguice/roboguice/wiki /Your-First-Custom-Binding - person Eugen Martynov; 04.02.2015
comment
Ето как да замените инжекциите в теста: github.com/roboguice/roboguice/blob/master/astroboy/src/test/ - person Eugen Martynov; 04.02.2015
comment
Здравейте, благодаря Eugen, определено ще ги разгледам. - person Hilfritz; 04.02.2015

Robolectric вече съдържа фалшив http слой, където можете да подготвите отговори.

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

person nenick    schedule 10.02.2015